学校校园网站建设实施方案,凡客登录入口,摄影网站源码 国外,做淘宝客怎么建网站描述 Midway 是一个适用于构建 Serverless 服务#xff0c;传统应用、微服务#xff0c;小程序后端的 Node.js 框架。 Midway 可以使用 Koa#xff0c;Express 或 Egg.js 作为基础 Web 框架。它还提供了独立使用的基本解决方案#xff0c;例如 Socket.io#xff0c;GRPC传统应用、微服务小程序后端的 Node.js 框架。 Midway 可以使用 KoaExpress 或 Egg.js 作为基础 Web 框架。它还提供了独立使用的基本解决方案例如 Socket.ioGRPCDubbo.js 和 RabbitMQ 等。 此外Midway 也适用于前端/全栈开发人员的 Node.js 无服务器框架。构建下一个十年的应用程序。可在 AWS阿里云腾讯云和传统 VM /容器上运行。与 React 和 Vue 轻松集成。 特性 全功能支持 Web 应用/Serverless/FaaS/微服务/小程序后端等多种场景基于装饰器和依赖注入开发企业级应用 前端集成全新的云端一体应用研发体验零 API 调用使用 React Hooks 风格一体研发 跨平台支持部署至普通 Server 或 Serverless/FaaS 环境 扩展组件化扩展能力另外支持使用 Koa/Express/Egg.js 生态插件 示例: 官方提供多种场景的示例代码方便开发者快速上手 TypeScript 全面支持 快速入门 ❝ 如果你没有接触过 Midway没关系本章节我们将从实例的角度一步步地搭建出一个 Midway 标准应用展示天气信息让你能快速的入门 Midway。 初始化项目 我们推荐直接使用脚手架只需几条简单指令即可快速生成项目。 $ npm init midwaylatest -y 选择 koa-v3 项目进行初始化创建项目名可以自定比如 weather-sample。 现在可以启动应用来体验下。 $ npm run dev$ open http://localhost:7001 同时我们也提供了完整的实例可以在 npm init midway 之后选择 quick-start 项目创建即可方便对照学习。 编写 Controller 如果你熟悉 Web 开发或 MVC就知道第一步我们需要编写Controller 和 Router。 在脚手架创建的文件中我们已经有了一些文件我们暂时忽略他们。 在 controller 目录中新建一个 src/controller/weather.controller.ts 文件内容如下。 import { Controller, Get } from midwayjs/core;Controller(/)export class WeatherController { // 这里是装饰器定义一个路由 Get(/weather) async getWeatherInfo(): Promisestring { // 这里是 http 的返回可以直接返回字符串数字JSONBuffer 等 return Hello Weather!; }} 现在我们可以通过访问 /weather 接口返回数据了。 添加参数处理 在示例中我们需要一个 URL 参数来动态展示不同城市的天气。 通过添加 Query 装饰器我们可以获取到 URL 上的参数。 import { Controller, Get, Query } from midwayjs/core;Controller(/)export class WeatherController { Get(/weather) async getWeatherInfo(Query(cityId) cityId: string): Promisestring { return cityId; }} 除了 Query 装饰器Midway 也提供了其他请求参数的获取可以查看路由和控制文档。 编写 Service 在实际项目中Controller 一般用来接收请求参数校验参数不会包括特别复杂的逻辑复杂而复用的逻辑我们应该封装为 Service 文件。 我们来添加一个 Service 用来获取天气信息其中包括一个 http 请求获取远端的数据。 代码如下 // src/service/weather.service.tsimport { Provide, makeHttpRequest } from midwayjs/core;Provide()export class WeatherService { async getWeather(cityId: string) { return makeHttpRequest(https://midwayjs.org/resource/${cityId}.json, { dataType: json, }); }} ❝ makeHttpRequest 方法是 Midway 内置的 http 请求方法 然后我们来添加定义良好的类型定义可以帮助我们减少代码错误。 在 src/interface.ts 文件中我们增加天气信息的数据定义。 // src/interface.tsexport interface WeatherInfo { weatherinfo: { city: string; cityid: string; temp: string; WD: string; WS: string; SD: string; AP: string; njd: string; WSE: string; time: string; sm: string; isRadar: string; Radar: string; }} 这样我们就可以在 Service 中进行标注了。 import { Provide, makeHttpRequest } from midwayjs/core;import { WeatherInfo } from ../interface;Provide()export class WeatherService { async getWeather(cityId: string): PromiseWeatherInfo { const result await makeHttpRequestWeatherInfo(https://midwayjs.org/resource/${cityId}.json, { dataType: json, }); if (result.status 200) { return result.data as WeatherInfo; } }} ❝ 这里使用 Provide 装饰器修饰类便于后续 Controller 注入该类 同时我们修改下之前的 Controller 文件。 import { Controller, Get, Inject, Query } from midwayjs/core;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): PromiseWeatherInfo { return this.weatherService.getWeather(cityId); }} ❝ 这里使用 Inject 装饰器注入 WeatherService是 Midway 依赖注入的标准用法 这里也同步修改了方法的返回值类型 到这里我们可以请求 http://127.0.0.1:7001/weather?cityId101010100 查看返回的结果。 你的第一个 Midway 接口已经开发完成了你可以在前端代码中直接调用了接下去我们将利用这个接口完成一个服务端渲染的页面。 模板渲染 从这里开始我们需要用到一些 Midway 的扩展能力。 Midway 对应的扩展包我们称为 “组件”也是标准的 npm 包。 这里我们需要用到 midwayjs/view-nunjucks 组件。 可以使用下面的命令安装。 $ npm i midwayjs/view-nunjucks --save 安装完成后我们在 src/configuration.ts 文件中启用组件。 // ...import * as view from midwayjs/view-nunjucks;Configuration({ imports: [ koa, // ... view ], importConfigs: [join(__dirname, ./config)],})export class MainConfiguration { // ...} ❝ configuration 文件是 Midway 的生命周期入口文件承担了组件开关配置加载和生命周期管理的作用 imports 就使用来导入开启组件的方法 在 src/config/config.default.ts 中配置组件指定为 nunjucks 模板。 import { MidwayConfig } from midwayjs/core;export default { // ... view: { defaultViewEngine: nunjucks, },} as MidwayConfig; 在根目录非 src 里添加模板 view/info.html 文件内容如下 !DOCTYPE htmlhtml 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 classweather_bg div p {{city}}{{WD}}{{WS}} /p p classtemp{{temp}}sup℃/sup/p p 气压label{{AP}}/label /p p 湿度label{{SD}}/label /p /div /div /body/html 同时我们调整 Controller 的代码将返回 JSON 变为模板渲染。 // src/controller/weather.controller.tsimport { Controller, Get, Inject, Query } from midwayjs/core;import { WeatherService } from ../service/weather.service;import { Context } from midwayjs/koa;Controller(/)export class WeatherController { Inject() weatherService: WeatherService; Inject() ctx: Context; Get(/weather) async getWeatherInfo(Query(cityId) cityId: string): Promisevoid { const result await this.weatherService.getWeather(cityId); if (result) { await this.ctx.render(info, result.weatherinfo); } }} 到这一步我们访问 http://127.0.0.1:7001/weather?cityId101010100 已经可以看到渲染的模板内容了。 错误处理 别忘了我们还有一些异常的逻辑需要处理。 一般来说每个对外的调用都需要做异常捕获并且将异常转变为我们自己业务的错误这样才能有更好的体验。 为此我们需要定义一个我们自己的业务错误创建一个 src/error/weather.error.ts 文件。 // src/error/weather.error.tsimport { MidwayError } from midwayjs/core;export class WeatherEmptyDataError extends MidwayError { constructor(err?: Error) { super(weather data is empty, { cause: err, }); if (err?.stack) { this.stack err.stack; } }} 然后我们调整 Service 代码抛出异常。 // src/service/weather.service.tsimport { Provide, makeHttpRequest } from midwayjs/core;import { WeatherInfo } from ../interface;import { WeatherEmptyDataError } from ../error/weather.error;Provide()export class WeatherService { async getWeather(cityId: string): PromiseWeatherInfo { if (!cityId) { throw new WeatherEmptyDataError(); } try { const result await makeHttpRequestWeatherInfo(https://midwayjs.org/resource/${cityId}.json, { dataType: json, }); if (result.status 200) { return result.data as WeatherInfo; } } catch (error) { throw new WeatherEmptyDataError(error); } }} ❝ 将 http 的调用请求进行错误捕获将错误包裹返回一个我们系统的业务错误 如有必要我们可以定义更多的错误分配错误 Code 等 到这一步我们还需要将异常进行业务处理比如有多个位置抛出 WeatherEmptyDataError 时我们需要统一的格式返回。 错误处理器可以完成这个功能我们需要创建一个 src/filter/weather.filter.ts 文件内容如下 //src/filter/weather.filter.tsimport { Catch } from midwayjs/core;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 htmlbodyh1weather data is empty/h1/body/html; }} 然后应用到当前的框架中。 import { Configuration, App } from midwayjs/core;import * as koa from midwayjs/koa;import { WeatherErrorFilter } from ./filter/weather.filter;// ...Configuration({ // ...})export class MainConfiguration { App() app: koa.Application; async onReady() { // ... // add filter this.app.useFilter([WeatherErrorFilter]); }} 这样当每次请求中获取到了 WeatherEmptyDataError 错误会使用相同的返回值返回给浏览器同时会在日志中记录原始的错误信息。 数据模拟 在编写代码时我们的接口经常还处在无法使用的阶段为了尽可能降低影响可以使用模拟数据来代替。 比如我们的天气接口就可以在本地和测试环境模拟掉。 我们需要创建一个 src/mock/data.mock.ts 文件内容如下 // src/mock/data.mock.tsimport { Mock, ISimulation, App, Inject, IMidwayApplication, MidwayMockService,} from midwayjs/core;import { WeatherService } from ../service/weather.service;Mock()export class WeatherDataMock implements ISimulation { App() app: IMidwayApplication; Inject() mockService: MidwayMockService; async setup(): Promisevoid { const originMethod WeatherService.prototype.getWeather; this.mockService.mockClassProperty( WeatherService, getWeather, async cityId { if (cityId 101010100) { return { weatherinfo: { city: 北京, cityid: 101010100, temp: 27.9, WD: 南风, WS: 小于3级, SD: 28%, AP: 1002hPa, njd: 暂无实况, WSE: 3, time: 17:55, sm: 2.1, isRadar: 1, Radar: JC_RADAR_AZ9010_JB, }, }; } else { return originMethod.apply(this, [cityId]); } } ); } enableCondition(): boolean | Promiseboolean { // 模拟类启用的条件 return [local, test, unittest].includes(this.app.getEnv()); }} WeatherDataMock 类用于模拟天气数据其中的 setup 方法用于实际的初始化模拟其中我们使用了内置的 MidwayMockService 的 mockClassProperty 方法将 WeatherService 的 getWeather 方法模拟掉。 在模拟过程中我们仅仅将单个城市的数据进行了处理其他依旧走了原来的接口。 enableCondition 用于标识这个模拟类在哪些场景下生效比如我们上面的代码就仅在本地和测试环境生效。 这样当本地开发和测试时我们请求 101010100 的数据将直接被拦截和返回且在部署到服务器环境后也不会受到影响。 单元测试 Midway 默认使用 jest 作为基础的测试框架一般我们的测试文件会放在根目录的 test 目录中以 *.test.ts 作为后缀。 比如我们要测试编写的 /weather 接口。 我们需要测试它的成功和失败两种状态。 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 createAppFramework(); }); 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/); });}); 执行测试 $ npm run test 就这么简单更多请参见测试 ❝ jest 测试时以单文件作为单位使用 beforeAll 和 afterAll 控制 app 的启停 使用 createHttpRequest 来创建一个测试请求 使用 expect 来断言返回的结果是否符合预期 文档和社区 官网 ❝ 关注公众号「开源地带」获取更多干货实践欢迎交流分享~ 本文由 mdnice 多平台发布