文章目录

  • 搭建node 环境
    • 通过babel 搭建node环境
    • 通过 typeScirpt搭建环境
  • 通过装饰器改造路由

搭建node 环境

通过babel 搭建node环境

npm install --save-dev babel-register
npm install --save-dev babel-plugin-transform-decorators-legacy
//支持装饰器语法
npm install --save-dev babel-preset-stage-3
//
npm install --save-dev babel-preset-env
// 我们可以使用babel-preset-env这个插件,它会自动检测当前node版本,只转码node不支持的语法,非常方便
npm install --save babel-polyfill
// babel转码时不能识别一些全局对象的API,例如Object.assign,使用它可以解决这个问题
根目录新建start.js文件

//start.js
require('babel-register')({// "presets": [//   "stage-3",//   ["env",{//     "targets":{//       "node":'current'//     }//   }]// ],"plugins":['transform-decorators-legacy']
})
require('babel-polyfill');
require('./test.js');

根目录新建test.js文件

//test.js
const router = conf => (target, key, desc) => {console.log(conf, target, key, desc, '----')
}
const post = path => {console.log('path', path);return router({path,});
}
class UserController {@post('login')login() {}
}
const a = async () => {console.log('await test a')return await 1;}
console.log(a(),'await ');

node start.js //启动项目

通过 typeScirpt搭建环境

根目录新建tsconfig.json

{"compilerOptions": {"declaration": false,"emitDecoratorMetadata": true,"experimentalDecorators": true,"lib": ["es2015","es2016","es2017","es2018","esnext",],"module": "commonjs","moduleResolution": "node","noImplicitThis": false,"noImplicitReturns": true,"outDir": "dist","sourceMap": false,"strict": true,"target": "es2015",},"exclude": ["node_modules","dist"]
}

npm -g typscript //ts 全局安装

修改package.json

"scripts": {"template":"tsc","start":"node dist/test.js"
}

npm run template //编译ts

npm run start //启动项目

通过装饰器改造路由

对路由封装

import Router from 'koa-router'
import glob from 'glob'
import { resolve } from 'path';
import _ from 'lodash';
/*** 以键值对存放路由信息* key {*    target  //存放路由前缀*    method  请求方法*    path 请求路由* }* value 存放被装饰器过后的方法*  */
export let routersMap = new Map();
export const symbolPrefix = Symbol('prefix');
export const isArray = v => _.isArray(v) ? v : [v]
//给路径添加前缀 /
export const normalizePath = path => path.startsWith('/') ? path : `/${path}`;export default class Route {constructor(app, apiPath) {this.app = app;//实例路由this.router = new Router();this.apiPath = apiPath;}//init() {//引入所有路由文件glob.sync(resolve(this.apiPath, './*.js')).forEach(require);// this.router.get('/', async (ctx) => {//   ctx.body = 'hello world';// })//挂载路由for (let [conf, controller] of routersMap) {const controllers = isArray(controller);let prefixPath = conf.target[symbolPrefix];if (prefixPath) prefixPath = normalizePath(prefixPath);const routerPath = prefixPath + conf.path;this.router[conf.method](routerPath,...controllers);}this.app.use(this.router.routes());this.app.use(this.router.allowedMethods());}
}export const router = conf => (target, key, desc) => {conf.path = normalizePath(conf.path)routersMap.set({target: target,...conf}, target[key])
}
// controller装饰器
export const controller = path => target => target.prototype[symbolPrefix] = pathexport const get = path => router({method: 'get',path: path
})export const post = path => router({method: 'post',path: path
})export const put = path => router({method: 'put',path: path
})export const del = path => router({method: 'delete',path: path
})

新建routersm目录

//routers/user
import { controller, put, del, post, get, required } from '../decorator/router'
import config from '../config'
import {resError, resSuccess} from '../utils/resHandle'
@controller(`${config.APP.ROOT_PATH}/user`)
export class userController{//获取用户信息@get('/:id')async getUserInfo(ctx){resSuccess({ctx,message:'获取用户信息',result:ctx.params})}//登录@post('login')  async Login(ctx,next){const {username,password}=ctx.request.body;try {resSuccess({ctx,message:'login success'})} catch (error) {resError({ ctx, message: "login Error!" })}}//退出async LoginOut(ctx,next){}
}

信息反馈的封装

//对请求响应统一处理
export const resError = ({ ctx, message = '请求失败', err = null }) => {ctx.body = { code: 0, message, debug: err }
}export const resSuccess = ({ ctx, message = '请求成功', result = null }) => {ctx.body = { code: 1, message, result }
}

新建启动文件和主文件

//start.js
const { resolve } = require('path')
//用于支持 es6语法
require('babel-register')({'presets': ['stage-3',["latest-node", { "target": "current" }]],'plugins': ['transform-decorators-legacy']
})require('babel-polyfill')
require('./app')//app.js
import Koa from 'koa'
import config from './config'
import Route from './decorator/router'
import { resolve } from 'path';
const app = new Koa();//使用中间件
//引用路由
const router = new Route(app, resolve(__dirname, './routers'))
//初始化路由
router.init();
//启动服务
app.listen(config.APP.PORT, () => {console.log(`node-koa api run port at ${config.APP.PORT}`);
})

关于配置文件

const APP = {ROOT_PATH: '/api',LIMIT: 10,PORT: 3009
}
export default{APP
}

本文来自对 naice-blog-koa 学习仅供参考。

换种方式去写node API相关推荐

  1. 换种方式去分页(转)

    为什么要换种方式分页,一个字:太慢了     分页要传入的参数,1:页号,2:行数     分页要取到的数据, 1:总行数,2:单页数据 http://www.cnblogs.com/mikedeng ...

  2. 技术人生感悟之陈果:如果你累了,就换一种方式去生活

    复旦大学教授陈果在<好的孤独>中说:"换一种看法,便是换一种活法." 世间的活法有千万种,总会有一种是适合我们的. 人生苦短,如果你觉得累了,不如就换一种活法. 1.一 ...

  3. 避免回调地狱的解决方案 async/await:用同步的方式去写异步代码

    文章目录 前言 一.引入异步编程 二.常见处理异步编程的几种方式 1.Generator函数 2.Promise函数 3.async/await 总结 前言 这篇文章主要给大家分享一下,自己关于异步编 ...

  4. 【Java基础】IO流概述分类、字节流写数据、字节流写数据的三种方式及写数据的两个小问题

    目录 一.IO流概述和分类 二.字节流写数据 三.字节流写数据的三种方式 四.字节流写数据的两个小问题 一.IO流概述和分类 IO流介绍: ● IO:输入/输出(Input/Output) ● 流:是 ...

  5. 换一种方式去思考--microsoft for win server03

    微软的东西被很多人鄙视. 原因是蔽塞,但大部分是无奈. 域环境下实现的强大功能是其他系统所不能比拟的. 沿用这样的战略思路.只要小盖开心,可以让全球的MS系统计算机组建成微软计算机群的大军. 这也是 ...

  6. 【第21期】以实际项目作驱动,换种方式学Java

    Java作为OOP(面向对象编程)的集大成者,融合了其他语言的诸多优点,让开发者体验到了函数式编程的精妙及强大之处. 随着这几年开源社区的蓬勃发展,越来越多的组件.框架.方案如雨后春笋般涌现,现代工程 ...

  7. 企业拜年,今年可以换种方式了

    就在刚刚,老板一脸严肃的走到我身边 在他沉默的3秒钟里,我有种不详的预感 努力工作了一年 老板不会通知我年终奖泡汤了吧,呜呜 "小白,你擅长策划,春节你觉得用什么方式与用户互动比较好?&qu ...

  8. 奥睿科硬盘柜linux下识别,云盘不靠谱?是时候换种方式解决存储问题了 — 奥睿科 多盘位硬盘柜阵列柜评测...

    如今不管是电脑还是其他数码设备(手机等),性能都得到飞跃发展,一部高清电影动不动就是10G.20G,而一部3A游戏大作更有可能高达40G~50G.一般电脑.手机.平板的容量已经不能适应这类需求,这就需 ...

  9. linux换桌面窗口管理器,Awesome 窗口管理器——换种方式使用星际译王

    星际译王被广泛使用的两个功能应该是划词翻译和手动输入翻译.由于星际译王缺少划词功能的开关快捷键,导致每次划词功能使用结束后,必须手动关闭此功能. 否则在 vim 视图模式下选择文本的时候会弹出不需要的 ...

最新文章

  1. Spring Cloud构建微服务架构:分布式配置中心(加密解密)
  2. HDU - 6661 Acesrc and String Theory (后缀数组)
  3. git 移动分支指针_理解git 中的HEAD指针branch指针
  4. servlet如何使用session把用户的手机号修改_SpringBoot源码学习系列之嵌入式Servlet容器...
  5. 如何在dorado中自定义导出
  6. 如何动态确认每个输入的值都符合设定域
  7. java实例成员与类成员区别_Java之实例成员与类成员
  8. 【优化算法】天牛须搜索优化粒子群算法【含Matlab源码 1256期】
  9. (Django开发)免费HTML模板资源集合
  10. PCL库实时显示点云流
  11. MySQL实战第二十二讲-MySQL有哪些“饮鸩止渴”提高性能的方法?
  12. 基于mindwave脑电波进行疲劳检测算法的设计(5)
  13. NYOJ_1273_宣传墙
  14. 支付宝沙箱测试手机网站支付,提示商户合作协议已到期,无法继续使用
  15. TM4C123GXL驱动安装
  16. VRRPv2和VRRPv3对比区别
  17. 转:python各种库
  18. 【QPSK中频】基于FPGA的QPSK中频信号产生模块verilog设计
  19. TPFanControl.ini
  20. oracle 分页公式

热门文章

  1. 批量读取txt文件中的内容进入csv文件
  2. 国产公链“皇帝的新衣”,到底还有多少个元年?
  3. 小程序传参中文乱码解决办法
  4. 基于web前端技术的中国围棋
  5. ESP8266-使用浏览器动态连接路由器
  6. 嘿,来做一个“币”的生意吗?Android仿火币K线图实现!
  7. wxpy识别语音消息
  8. 苹果商务本能matlab吗,iMac
  9. jQuery DataTables 使用方法整理
  10. 航海热线为什么服务器维护中,7月27日亚特兰蒂斯服务器维护公告