最近 和别人一块运维 开源 产品,后台需要用到 midway框架,所以进行学习。

首先就是midway的搭建,

首先 npm init midway ,初始化项目,选择 koa-v3 template

启动项目 npm run dev,此刻对应后台地址可以访问。

编写Controller

import { Controller,Get } from '@midwayjs/decorator';

@Controller('/')
export class WeatherController{

  @Get('/weather')      
  async getWeatherInfo():Promise<string>{
     return "Hello Weather!";
  }  
}

添加参数处理

import { Controller,Get,Query } from '@midwayjs/decorator';

@Controller('/')
export class WeatherController{
  @Get('/weather')
  async getWeatherInfo(@Query('id') cityId:string):Promise<string>    
 {
      return cityId;  
 }    
}

编写Service

 

import { Provide } from '@midwayjs/decorator';
import { makeHttpRequest } from '@midwayjs/core';
import { WeatherInfo } from '../interface';

@Provide()
export class WeatherService{
   async getWeather(cityId:string):Promise<WeatherInfo>  {
       const result = await makeHttpReauest(`http://www.weather.com.cn/data/cityinfo/${cityId}.html`,{
      dataType:'json'  
    });
    if(result.state===200){
        return result.data;
    }  
   }
}

 

在service里面 @Provide()是用来注入

在Controller中进行注入

@Inject()

weather:Weather;

weather.controller.ts代码修改如下

import { Controller,Get,Inject,Query } from '@midwayjs/decorator';
import { WeatherInfo } from '../interface';
import { WeatherService } from '../service/weather.service';

@Controller('/')
export class WeatherController{

  @Inject()
  weatherService:WeatherService;

  @Get('/weather')      
  async getWeatherInfo(@Query('cityId') cityid:string):Promise<WeatherInfo>{
     return this.weatherService.getWeather(cityid);
  }  
}

 

模板渲染

使用view-nunjucks组件

npm i @midwayjs/view-nunjucks --save

安装好组件之后在src/configuration.ts文件中启用组件

 import * as view from '@midwayjs/view-nunjucks';

@Configuration({

  import[view],

       importConfigs:[join(_dirname,'./config')]

})

 然后在src/config/config.default.ts中配置组件,指定 nunjucks模板。

import { MidwayConfig } from '@midwayjs/core';

export default{
  view:{
       defaultViewEngine: 'nunjucks'
    }  
}    

然后在根目录设置模板内容,view/info.html

<!DOCTYPE html>
<html>
  <head>
    <title>天气预报</title>
    <style>
      .weather_bg {
        background-color: #0d68bc; 
        height: 150px;
        color: #fff;
        font-size: 12px;
        line-height: 1em;
        text-align: center;
        padding: 10px;
      }

      .weather_bg label {
        line-height: 1.5em;
        text-align: center;
        text-shadow: 1px 1px 1px #555;
        background: #afdb00;
        width: 100px;
        display: inline-block;
        margin-left: 10px;
      }

      .weather_bg .temp {
        font-size: 32px;
        margin-top: 5px;
        padding-left: 14px;
      }
      .weather_bg sup {
        font-size: 0.5em;
      }
    </style>
  </head>
  <body>
    <div class="weather_bg">
      <div>
        <p>
          {{city}}({{WD}}{{WS}})
        </p>
        <p class="temp">{{temp}}<sup></sup></p>
        <p>
          气压<label>{{AP}}</label>
        </p>
        <p>
          湿度<label>{{SD}}</label>
        </p>
      </div>
    </div>
  </body>
</html>

然后调整Controller代码,将返回JSON变成模板渲染

主要是用 @midwayjs/koa 里面的Context 

this.ctx.render('info',result.weather);

 

错误处理

定义错误 在src/error/weather.error.ts

import { MidwayError } from '@midwayjs/core';

export class WeatherEmptyDataError extends MidwayError{

  constructor(err?:Error){

    super('weather data is empty',{

      cause:error
    });
    if(err?.stack){

      this.stack = err.stack;
    }
  }

} 

在service代码中进行抛出错误

throw new WeatherEmptyDataError

通过拦截器进行错误处理

在src/filter/weather.filter.ts中进行处理

import { Catch } from '@midwayjs/decorator';

import { Context } from '@midwayjs/koa';

import { WeatherEmptyDataError } from '../error/weather.error';



@Catch(WeatherEmptyDataError)

export class WeatherErrorFilter{

  async catch(err:WeatherEmptyDataError,ctx:context){

    ctx.logger.error(err);
    return '<html><body><h1>weather data is empty</h1></body></html>';
  }

}

然后在生命周期ready时候启用filter

在ContainerLifeCycle中的OnReady

里面启用this.app.useFilter([ WeatherErrorFilter ]);

 

 

单元测试

import { createApp, close, createHttpRequest } from '@midwayjs/mock';
import { Framework, Application } from '@midwayjs/koa';

describe('test/controller/weather.test.ts', () => {

let app: Application;
beforeAll(async () => {
// create app
app = await createApp<Framework>();
});

afterAll(async () => {
// close app
await close(app);
});

it('should test /weather with success request', async () => {
// make request
const result = await createHttpRequest(app).get('/weather').query({ cityId: 101010100 });

expect(result.status).toBe(200);
expect(result.text).toMatch(/北京/);
});

it('should test /weather with fail request', async () => {
const result = await createHttpRequest(app).get('/weather');

expect(result.status).toBe(200);
expect(result.text).toMatch(/weather data is empty/);
});
});

 

posted on 2022-09-24 13:43  小迷瞪  阅读(420)  评论(0编辑  收藏  举报