抛弃Promise,Nestjs 使用 Rxjs 来处理异步请求

首先需要注意的是,之前从@nestjs/common导入的HttpService的方式已被废弃而不可用。
新方式是通过安装@nestjs/axios包来导入所需的模块和服务。

所有 HttpService 的方法都返回一个包裹在 Observable 对象内的 AxiosResponse 。例如get post put等。

通过返回 RxJS observable 流,Nest 路由处理程序将更加强大。 Nest 将自动订阅下面的源并获取最后发出的值(在流完成后)。

下面以一个简单地微信小程序服务端code2session接口为范例

app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MongooseModule } from '@nestjs/mongoose'
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TodoModule } from './todo/todo.module';
import { HttpModule } from '@nestjs/axios';

@Module({
  imports: [
    HttpModule,
    TodoModule,
    ConfigModule.forRoot(),
    MongooseModule.forRoot(`mongodb://${new ConfigService().get('DATABASE_HOST')}`)
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule { }

app.service.ts

import { HttpService } from '@nestjs/axios';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Observable } from 'rxjs';
import { AxiosResponse } from 'axios'

const errorCode: Map<number, string> = new Map([
  [-1, '系统繁忙,此时请开发者稍候再试	'],
  [0, '请求成功'],
  [40029, 'code 无效'],
  [45011, '频率限制,每个用户每分钟100次'],
  [40226, '高风险等级用户,小程序登录拦截'],
])

@Injectable()
export class AppService {
  private readonly wxAppId: string;
  private readonly wxAppSecret: string;
  constructor(private readonly httpService: HttpService, private readonly configService: ConfigService) {
    this.wxAppId = configService.get('WX_APPID')
    this.wxAppSecret = configService.get('WX_APPSECRET')
    this.httpService.axiosRef.interceptors.response.use(({data}) => {
//设置Axios的拦截器,直接返回 AxiosResponse.data
      data.tips = errorCode.get(data.errcode)
      return data
    })
  }
  login(): string {
    return 'Hello World!';
  }
  wxLogin(code: string): Observable<AxiosResponse<{
    errcode: number,
    errmsg: string,
    tips: string
  }>> {
    const api = `https://api.weixin.qq.com/sns/jscode2session?appid=${this.wxAppId}&secret=${this.wxAppSecret}&js_code=${code}&grant_type=authorization_code`
    return this.httpService.get(api)//直接返回Observable对象
  }
}

app.controller.ts

import { Body, Controller, Get, Post, UsePipes, ValidationPipe } from '@nestjs/common';
import { AxiosResponse } from 'axios';
import { IsNotEmpty, IsString } from 'class-validator';
import { from, map, Observable, of } from 'rxjs';
import { AppService } from './app.service';

class code2sessionDto {
  @IsString({
    message: 'code 必须为字符串'
  })
  @IsNotEmpty({
    message: 'code 不能为空'
  })
  code: string
}

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) { }
  @Post('login')
  login() {
    return 'login'
  }
  @Post('wxlogin')
  wxLogin(@Body() params: code2sessionDto) {
    return this.appService.wxLogin(params.code)//nestjs会自动订阅
  }
}
抛弃Promise,Nestjs 使用 Rxjs 来处理异步请求插图
返回值
{
    "errcode": 40029,
    "errmsg": "invalid code, rid: 62aa10e4-53bc13f6-17909902",
    "tips": "code 无效"
}