背景:
1、expres express简易的基于nodejs搭建的一个web容器,它基于ES5的语法,要实现异步代码,只能通过回调的形式来实行,但是如果异步嵌套的层次过大,就会导致代码非常难看 如下:
const express = require('express')
const app = express()
app.get('/', function(req, res) {
res.send('Hello world')
})
app.listen(3000, function() {
console.log('express is listening is 3000')
})
2、koa1.0 随着新版node.js开始支持ES6,express团队又基于generator重新编写了新一代的web框架koa,和express相比,koa1.0使用generator实现异步,代码看起来同步
var koa = require('koa');
var app = koa()
app.use('/', function* () {
yield fn();
var data = yield fn2()
this.body = data
})
app.listen(3000)
但是这样写有个问题就是,generator的本意并不是异步,Promise才是为异步设计的,但是promise 的写法,我们就要一直.then().then()想想就可怕~~
3、koa2.0的问世是来至于es7提案的async和await,async-await解决了generator 的回调地狱问题
import Koa from 'koa'
const app = new Koa()
app.use(async (ctx, next) => {
await next()
let data = await someFn()
ctx.response.type = 'text/plain'
ctx.response.body = data
})
koa设计就是洋葱模型,先进后出,一层一层的中间件,可以自行定义,实现方法

话不多说,我们现在开始来搭建我们的koa2吧
项目初始化:
npm ini
npm install koa --save
// 基于koa-generator创建项目
npm install koa-generator -g
koa2 my-first-koa
接下来我们把项目的目录结构调整一下
---controller 专门处理业务的控制器
---error 专门处理报错的处理
------ApiError.js 报错提示方法
------ApiErrorNames.js 报错提示文案配置
------index.js 导出报错方法
---middleware 项目中间件
---plugins 项目第三方依赖,配置文件等
---routers 路由文件
---utils 工具方法
---app.js 主文件
---index.js 入口文件
---package.json 项目配置
为方便使用es6语法,import等方法,我们在执行安装以下2个安装包
npm install babel-register --save
npm install babel-polyfill --save
接下来调整我们的项目文件配置,
首先将index.js文件修改成如下
require('babel-register')
require('babel-polyfill')
//set app
const app = require('./app')
module.exports = app
将bin下的www修改如下
// 原先:
var app = require('../app');
// 修改为:
var app = require('../index');
app.js文件如下
import Koa from 'koa' // 进入koa模块
import json from 'koa-json' // 引入json模块解析
import onerror from 'koa-onerror' // 引入报错
import bodyparser from 'koa-bodyparser' // 请求数据解析
// 引入token校验
import tokenVerify from './middleware/tokenVerify'
// 引入返回响应体公共处理模块
import responseFilter from './middleware/responseFilter'
onerror(app)
app.use(bodyparser())
app.use(json())
app.use(tokenVerify)
app.use(responseFilter())
responseFilter方法的实现
// 导入到处模块
import ApiError from '../error/ApiError'
module.exports = function() {
return async function(ctx, next) {
try {
await next();
responseFormatter(ctx)
} catch (error) {
// 这一块主要处理,在执行数据查询的时候,抛出异常进行全局拦截
if (error instanceof ApiError) {
ctx.status = 200;
ctx.body = {
code: error.code,
message: error.message
}
}
}
}
}
const responseFormatter = ctx => {
// 这里是对返回来的数据库数据进行统一的数据格式
if (ctx.body) {
ctx.body = {
code: 200,
message: '',
data: ctx.body
}
}
}
ApiError方法实现如下
import ApiErrorNames from './ApiErrorNames'
function ApiError(names) {
Error.call(this)
let errorInfo = ApiErrorNames.getErrorInfo(names)
this.code = errorInfo.code
this.message = errorInfo.message
}
ApiError.prototype = Object.create(Error.prototype)
export default ApiError
ApiErrorNames文件如下配置
const ApiErrorNames = {
InvalidToken: { code: 401, message: 'token无效' },
InvalidUser: { code: 1001, message: '无效的用户' }
}
ApiErrorNames.getErrorInfo = (errorInfo) => {
if (!errorInfo) {
errorInfo = ApiErrorNames.UnknownError
}
return errorInfo
}
export default ApiErrorNames
接下来我们实现一个login路由,将我们上述的文件联动起来 在controller下新建userController.js
在routers下新增user.js 并在app.js中,引入user路由
// app.js引入
import users from './routes/users'
// 注册users路由
app.use(users.routes(), users.allowedMethods())
routes/user.js代码实现如下:
import UserController from "../controller/userController" // 导入用户控制器
const Router = require('koa-router') // 导入koa路由
// 设置路由前缀名,如果路由过于多的话,这个方法会十分有效
const router = new Router({
prefix: '/user'
});
router.post('/login', UserController.login)
module.exports = router
controller/userController.js代码实现如下
import {
ApiError,
ApiErrorNames
} from '../error'
class UserController {
static async login(ctx) {
// 获取用户提交过来信息
let {
name,password
} = ctx.request.body
// ...查询数据库一系列操作
// 用户不存在
throw new ApiError(ApiErrorNames.InvalidUser)
// 用户存在
ctx.body = data
}
}
export default UserController;
接下来通过node启动我们的服务
npm run start
通过api接口或者前端页面进行接口请求
post http://localhost:端口号/user/login
这样就可以愉快的开发我们nodejs服务层的api接口了
我是godlike,每周一篇小技巧,一起快速入坑,希望能在前端道路上,和你努力,一起共勉!