美文网首页
Koa2学习系列02-中间件用法——讲解 Koa2 中间件的用法

Koa2学习系列02-中间件用法——讲解 Koa2 中间件的用法

作者: wanminglei | 来源:发表于2020-05-11 11:24 被阅读0次

    middleware 中间件

    正是因为中间件的扩展性才使得 Koa 的代码简单灵活。

    app.js 中,有这样一段代码:

    app.use(async (ctx, next)=>{ 
       await next() 
       ctx.response.type = 'text/html' 
       ctx.response.body = '<h1>Hello World</h1>' 
     })
    

    它的作用是:每收到一个 http 请求,Koa 都会调用通过 app.use() 注册的 async 函数,同时为该函数传入 ctxnext两个参数。而这个 async 函数就是我们所说的中间件。

    下面我们简单介绍一下传入中间件的两个参数。

    ctx

    ctx 作为上下文使用,包含了基本的 ctx.requestctx.response。另外,还对 Koa 内部对一些常用的属性或者方法做了代理操作,使得我们可以直接通过 ctx 获取。比如,ctx.request.url 可以写成 ctx.url

    除此之外,Koa 还约定了一个中间件的存储空间 ctx.state。通过 state 可以存储一些数据,比如用户数据,版本信息等。如果你使用 webpack 打包的话,可以使用中间件,将加载资源的方法作为 ctx.state 的属性传入到 view 层,方便获取资源路径。

    next

    next 参数的作用是将处理的控制权转交给下一个中间件,而 next() 后面的代码,将会在下一个中间件及后面的中间件(如果有的话)执行结束后再执行。

    注意: 中间件的顺序很重要!

    我们重写 app.js 来解释下中间件的流转过程:

    // 按照官方示例
    const Koa = require('koa')
    const app = new Koa() 
    // 记录执行的时间
    app.use(async (ctx, next) => { 
       let stime = new Date().getTime() 
       await next()  
       let etime = new Date().getTime() 
       ctx.response.type = 'text/html'  
       ctx.response.body = '<h1>Hello World</h1>' 
       console.log(`请求地址: ${ctx.path},响应时间:${etime - stime}ms`)
    });
    
     app.use(async (ctx, next) => { 
       console.log('中间件1 doSomething')  
       await next();  
       console.log('中间件1 end')
    })
    
     app.use(async (ctx, next) => {  
       console.log('中间件2 doSomething')  
       await next(); 
       console.log('中间件2 end')
    })
    
     app.use(async (ctx, next) => { 
         console.log('中间件3 doSomething') 
         await next(); 
         console.log('中间件3 end')
    })
    
     app.listen(3000, () => {
        console.log('server is running at http://localhost:3000')
    })
    

    运行起来后,控制台显示:

    server is running at http://localhost:3000
    
    

    然后打开浏览器,访问 http://localhost:3000,控制台显示内容更新为:

    server is running at http://localhost:3000
    中间件1 doSomething
    中间件2 doSomething
    中间件3 doSomething
    中间件3 end
    中间件2 end
    中间件1 end
    请求地址: /,响应时间:2ms
    

    从结果上可以看到,流程是一层层的打开,然后一层层的闭合,像是剥洋葱一样 —— 洋葱模型。

    此外,如果一个中间件没有调用 await next(),会怎样呢?答案是『后面的中间件将不会执行』

    修改 app.js 如下,我们去掉了第三个中间件里面的 await

    // 按照官方示例
    const Koa = require('koa')
    const app = new Koa() 
    // 记录执行的时间
    app.use(async (ctx, next) => { 
       let stime = new Date().getTime() 
       await next()  
       let etime = new Date().getTime() 
       ctx.response.type = 'text/html'  
       ctx.response.body = '<h1>Hello World</h1>' 
       console.log(`请求地址: ${ctx.path},响应时间:${etime - stime}ms`)
    });
    
     app.use(async (ctx, next) => { 
       console.log('中间件1 doSomething')  
       await next();  
       console.log('中间件1 end')
    })
    
     app.use(async (ctx, next) => {  
       console.log('中间件2 doSomething')  
      // 注意,这里我们删掉了 next
      // await next()
       console.log('中间件2 end')
    })
    
     app.use(async (ctx, next) => { 
         console.log('中间件3 doSomething') 
         await next(); 
         console.log('中间件3 end')
    })
    
     app.listen(3000, () => {
        console.log('server is running at http://localhost:3000')
    })
    

    重新运行代码后,控制台显示如下:

        server is running at http://localhost:3000
        中间件1 doSomething
        中间件2 doSomething
        中间件2 end
        中间件1 end
        请求地址: /,响应时间:1ms
    

    与我们的预期结果『后面的中间件将不会执行』是一致的。

    下一节中,我们将学习下如何响应浏览器的各种请求。

    原文https://github.com/ikcamp/koa2-tutorial/tree/1-middleware

    相关文章

      网友评论

          本文标题:Koa2学习系列02-中间件用法——讲解 Koa2 中间件的用法

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