美文网首页
koa2中间件的调用顺序

koa2中间件的调用顺序

作者: 易路先登 | 来源:发表于2019-06-27 06:56 被阅读0次

找不到合适的描述方式,顺着序号读粗体字,如粗体字描述的结论不明白,再参照其后面的代码片段及代码说明去理解koa2中间件的调用顺序。

koa2中的中间件使用如下:

app.use((ctx,next)=>{
  next();
});
app.use((ctx,next)=>{
  next();
});
...

1 next()相当于对下一个中间件函数进行调用

而且next()的值相当于下一个中间件函数的返回值

app.use((ctx,next)=>{
  let testStr = next();
  conslole.log(testStr);//Promise { undefined }
});
app.use(middleware2);
...
function middleware2(ctx,next){
  next();
  return "test";
}

这段代码的运行结果大体相当于如下代码片段

app.use((ctx,next)=>{
   let testStr = middleware2(ctx,next);
   conslole.log(testStr);//undefined 
});
...
function middleware2(ctx,next){
  next();
  return "test";
}

2 koa2默认对中间件函数进行了promise封装。

app.use((ctx,next)=>{
  var result = middleware2(ctx,next);
  console.log(result);//undefined
});
...
function middleware2(ctx,next){
  next();
}

运行打印结果为undefined
改写代码为:

app.use((ctx,next)=>{
  var result = next();
  console.log(result);//Promise { undefined }
});
app.use((ctx,next)=>{
  next();
});
...

运行打印结果为Promise { undefined },可见koa2默认对中间件函数进行了promise封装。

3 上一个中间件的next()可以拿到下一个中间件的返回值,并封装进返回的promise对象中

以下代码:

app.use((ctx,next)=>{
  var result = next();
  console.log(result);//Promise { "testStr" }
});
app.use((ctx,next)=>{
  next();
  return "testStr";
});
...

运行打印结果为Promise { "testStr" }

4 和普通的js函数调用一样,上一个中间中的next()对下一个中间件函数调用时,不会等待下一个中间件中异步代码。

以下代码:

app.use((ctx,next)=>{
  var result = next();
  console.log(result);//Promise { 0 }
});
app.use((ctx,next)=>{
  next();
  let num = 0;
  setTimeout(()=>{
    num = 3;
  },1000);
  return num;
});
...

运行打印结果为Promise { 0 }
以下代码:

app.use((ctx,next)=>{
  var result = next();
  console.log(result);//Promise { <pending> }
});
app.use((ctx,next)=>{
  next();
  return promiseFn();
});
...
function promiseFn(){
    return new Promise(function(resovle,reject){
        setTimeout(function(){
            resovle('5');
        },5000)
    });
}

运行打印结果为Promise { <pending> },pending为promise的进行中状态,意思就是并不等待promise的状态改变为resolved或fulfilled而立即返回一个“进行中”状态
如想要等待异步函数的返回结果,使next()的值为下一个中间件函数得异步代码值,那么可以使用asyncawait将代码改写为如下形式:

app.use(async(ctx,next)=>{
  var result = await next();
  console.log(result);//5
});
app.use((ctx,next)=>{
  next();
  return promiseFn();
});
...
function promiseFn(){
    return new Promise(function(resovle,reject){
        setTimeout(function(){
            resovle('5');
        },5000)
    });
}

如此就能拿到下一个中间件函数中的异步代码返回值了,输出结果为5
await关键字的意思是阻塞代码并对其后的表达式或函数调用进行取值
使用await关键字的话函数必须是async函数
但为了保证中间件的执行顺序,koa2规定如果某个中间件使用了await关键字,那么每一个中间件的next前面都应添加await关键字

6 中间件函数的执行顺序以next()为分隔呈洋葱型

app.use((ctx,next)=>{
  console.log('111');
  next();
  console.log('222');
});
app.use((ctx,next)=>{
  console.log('333');
  next();
  console.log('444');
});
...

输出顺序为:

//111
//333
//444
//222

因为next()相当于对下一个中间件函数的调用,以上代码相当于

  console.log('111');
  test(ctx,next);
  console.log('222');
  function test(ctx,next){
     console.log('333');
     next();
     console.log('444');
  }

输出顺序肯定为:

//111
//333
//444
//222

当仅在第二个中间件中使用await关键字时有可能破坏这个执行顺序

app.use((ctx,next)=>{
  console.log('111');
   var result =  next();
  console.log(result);//Promise { <pending> }
  console.log('222');
});
app.use(async(ctx,next)=>{
  console.log('333');
  next();
  let testVar = await  promiseFn();
  console.log('444');
});
...
function promiseFn(){
    return new Promise(function(resovle,reject){
        setTimeout(function(){
            resovle('5');
        },500)
    });
}

期待输出结果为:

//111
//333
//444
//222

输出结果却变为:

//111
//333
//222
//444

因为中间件1中的next()不会等待下一个中间件函数中的异步代码(即使阻塞)拿到Promise { <pending> }结果后继续往下执行打印222,然后等阻塞代码执行完后才打印444。造成中间件函数不再以next()为分隔呈洋葱模型执行,所以每一个next()前都必须添加await关键字。

app.use(async (ctx,next)=>{
  console.log('111');
   var result =  await next();
  //console.log(result);//undefined
  console.log('222');
});
app.use(async(ctx,next)=>{
  console.log('333');
  await next();
  let testVar = await  promiseFn();
  console.log('444');
});
...
function promiseFn(){
    return new Promise(function(resovle,reject){
        setTimeout(function(){
            resovle('5');
        },500)
    });
}

输出结果仍为:

//111
//333
//444
//222

如此就保证了koa2中的中间件函数按洋葱模型执行。

相关文章

  • koa2中间件的调用顺序

    找不到合适的描述方式,顺着序号读粗体字,如粗体字描述的结论不明白,再参照其后面的代码片段及代码说明去理解koa2中...

  • koa2中间件原理

    源码:koa-compose.js koa2的中间件流向是先按顺序执行next以前内容,然后对next以后内容进行...

  • koa和egg

    koa2 如上图,每一个请求都会一层层穿过中间件,最终在某个中间件处结束(不再继续调用下边的中间件),然后一层层返...

  • Django中间件的加载原理

    假设我们有如下中间件: setting.py文件 Django中间件的五个方法调用顺序如下: process_re...

  • Koa2教程(初识篇)

    目录一、定义二、安装三、koa中间件 系列教程Koa2教程(入门篇)Koa2教程(常用中间件篇) 一、定义 一个简...

  • 2.koa中间件

    1.创建一个自定义的中间件 2.使用中间件 调用的顺序 先进后出

  • koa2中间件原理

    koa2中间件的执行 koa2中间件的执行就像洋葱圈一样,从外面到最里面,再从最里面到最外面。 执行上述代码的结果...

  • iKcamp团队制作|基于Koa2搭建Node.js实战(含视频

    中间件用法——讲解 Koa2 中间件的用法及如何开发中间件 ?? iKcamp 制作团队 原创作者:大哼、阿干、...

  • express基础

    安装 (使用脚手架 express-generator) 中间件 中间件是一个函数,在请求和相应周期中被顺序调用

  • 知识点总结

    Koa2中间件 koa(面向node.js的表达式HTTP中间件框架)、koa-router(路由中间件)、koa...

网友评论

      本文标题:koa2中间件的调用顺序

      本文链接:https://www.haomeiwen.com/subject/akwkcctx.html