koa2路由问题


app.use(async(ctx, next) => {
    console.log('start'); // 第一步 
    await next(); //next() 出错找不到路由, 是因为没有等待下一个中间件处理结果?
    console.log('end');
})

app.use(async(ctx, next) => {
    var p = await new Promise(resovle => { //打印等了2S
        setTimeout(() => {
            resovle(10);
        }, 2000)
    })
    console.log(p);
    await next(); //next貌似没有被执行
})

app.use(async(ctx, next) => {
    ctx.body = 'hello world';
})

在使用koa2的路由时, 遇到了如上问题,望大牛指教~

阅读 5.6k
3 个回答

谢邀。

需要用await next(),不能只用next();

这得从koa中间件内部的实现原理说起。app.use(async fn)非常简单,大致如下,只是往middleware数组里push了个中间件方法。

use(fn) {
    this.middleware.push(fn);
}

app.listen(xx)里面,把 this.middleware 进行了一点封装(细节略),最终的结果就是,当http请求进来时,koa会循环调用中间件,如下(非源码)。

for(var i = 0; i < this.middleware.length; i++) {
    await this.middleware[i]();
}

实际koa源码里比上面代码稍微复杂点,封装逻辑主要是为了让await next()调用时,进入下一个中间件。下面这段是实际的源码,其他可以不看,单看next那里就行。

可以看到next里面调用了dispatch,这是个递归的过程,直到所有中间件调用完毕。

  return function (context, next) {
    // last called middleware #
    let index = -1
    return dispatch(0)
    function dispatch (i) {
      if (i <= index) return Promise.reject(new Error('next() called multiple times'))
      index = i
      let fn = middleware[i]
      if (i === middleware.length) fn = next
      if (!fn) return Promise.resolve()
      try {
        return Promise.resolve(fn(context, function next () {
          return dispatch(i + 1)
        }))
      } catch (err) {
        return Promise.reject(err)
      }
    }
  }

ctx.body = 'hello world';后面加一句await next();试试,不然中间件不会继续下去

代码

const Koa = require('koa');
const app = new Koa();

app.use(async (ctx, next) => {
  console.log('start'); // 第一步
  await next(); //next() 出错找不到路由, 是因为没有等待下一个中间件处理结果?
  console.log('end');
});

app.use(async (ctx, next) => {
  var p = await new Promise(resovle => { //打印等了2S
    setTimeout(() => {
      resovle(10);
    }, 2000);
  });
  console.log(p);
  await next(); //next貌似没有被执行
});

app.use(async (ctx, next) => {
  ctx.body = 'hello world';
});

app.listen(8088);

浏览器页面

clipboard.png
nodejs控制台输出

clipboard.png

综上,代码没有问题

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题