为什么放弃Express却使用Koa?

3,022 阅读3分钟

为什么大家都在用Koa,而弃掉Express呢?众所周知,Koa是由 Express 原班人马打造的致力于成为一个更小、更富有表现力、更健壮的 web 开发框架。

Express有自己的内置中间件,也实现了自己的路由,但是Koa只是轻量级的框架,没有自己内置的中间件和路由,只是继承了第三方中间件,但是跟Express有些不同。

express与koa的中间件到底有什么区别呢?

Koa解决了异步问题,首先我们先来看一个小例子:

这个例子就是分别用koa与express实现多个中间件运行,并且在第一个中间件执行完后,有个异步函数需要处理,此时,它们执行的结果一样吗?

看例子:

let express = require('express');
let app = express();
function log() {
    return new Promise((resolve,reject)=>{
        setTimeout(() => {
        resolve('我是异步成功要执行的结果');
    }, 1000);
})
}
app.use(async(req,res,next) => {
    console.log(1);
await next();
console.log(2);
})
app.use(async(req, res, next) => {
    console.log(3);
    let r = await log();
    console.log(r);
next();
console.log(4);
})
app.use((req, res, next) => {
    console.log(5);
next();
console.log(6);
})
app.listen(3000);

express的中间件next函数实现的方法:

function app() {
}
app.routes = [];
app.use = function (fn) {
  app.routes.push(fn);
}
function log() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('我是异步成功要执行的结果');
    }, 1000);
  })
}
app.use(async (req, res, next) => {
  console.log(1);
  await next(); 
  console.log(2);
})
app.use(async (req, res, next) => {
  console.log(3);
  let r = await log();
  console.log(r);
  next();
  console.log(4);
})
app.use((req, res, next) => {
  console.log(5);
  next();
  console.log(6);
})
let index = 0;
function next() {
  if (app.routes.length === index) return
  let route = app.routes[index++];
  route({}, {}, () => next());
}
next();

执行的结果为:

1
3
2
我是异步成功要执行的结果
5
6
4

同样的方法,我们看一下koa的基本方法和next的实现源理:

let Koa = require('koa');
let app = new Koa();
function log() {
    return new Promise((resolve,reject)=>{
        setTimeout(() => {
            resolve('我是异步成功要执行的结果');
        }, 1000);
    })
}
app.use(async(ctx,next)=>{
    console.log(1);
    // 第二个中间可能有异步逻辑,我们希望的是第一个中间件等待第二个中间件执行完再继续
    await next(); 
    console.log(2);
});
app.use(async (ctx, next) => {
    console.log(3);
    let r = await log();
    console.log(r);
    next();
    console.log(4);
});
app.use((ctx, next) => {
    console.log(5);
    next();
    console.log(6);
});
app.listen(3000);

注解:

  • 1.第一个中间件中如果等待的是一个promise 那么会等待这个promise执行完后 再执行剩下的,如果返回的是undefined,那么不会等待下一个人执行完后在执行;
  • 2.koa有个特点:中间件内部会处理一下 把他都变成promise;
function app() {
}
app.routes = [];
app.use = function (fn) {
  app.routes.push(fn);
}
function log() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('我是异步成功要执行的结果');
    }, 1000);
  })
}
app.use(async (req, res, next) => {
  console.log(1);
  await next(); 
  console.log(2);
})
app.use(async (req, res, next) => {
  console.log(3);
  let r = await log();
  console.log(r);
  next();
  console.log(4);
})
app.use((req, res, next) => {
  console.log(5);
  next();
  console.log(6);
})
let index = 0;
function next() {
  if (app.routes.length === index) return
  let route = app.routes[index++];
  // koa有个特点:中间件内部会处理一下 把他都变成promise
  return route({}, {}, () => next());
}
next();

执行结果为:

1
3
我是异步成功要执行的结果
5
6
4
2

总结:

通过上述的例子可以看出:

  • Express中间件不会等待下一个中间件完成
  • Koa会等待下一个中间完成
  • Koa解决了异步问题