express中间件和koa中间件的区别
发布于 7 年前 作者 zhuni 9083 次浏览 来自 问答

var express = require(‘express’); var app = express();

app.use(function middleware1(req, res, next) { console.log(‘middleware1 开始’); next(); console.log(‘middleware1 结束’); })

app.use(function middleware2(req, res, next) { console.log(‘middleware2 开始’); next(); console.log(‘middleware2 结束’); })

app.use(function middleware3(req, res, next) { console.log(‘middleware3 开始’); next(); console.log(‘middleware3 结束’); })

app.get(’/’, function (req, res) { res.send(‘Hello World!’); console.log(‘123456’) });

app.listen(3000, function () { console.log(‘Example app listening on port 3000!’); });

最后的输出结果是 ➜ express-demo node app.js Example app listening on port 3000! middleware1 开始 middleware2 开始 middleware3 开始 123456 middleware3 结束 middleware2 结束 middleware1 结束

请问一下这个和koa的洋葱模型有区别吗??

13 回复

不要用同步 不要用同步 不要用同步

你在controller里面加个异步操作看看? 自豪地采用 CNodeJS ionic

虽然结果是相似的。但是上面的代码实际上是这样,和 Koa 的*洋葱模型还是有区别的。

app.use(function middleware1(req, res, next) {
    console.log('middleware1 开始')
        // next()
        (function (req, res, next) {
            console.log('middleware2 开始')
                // next()
                (function (req, res, next) {
                    console.log('middleware3 开始')
                        // next()
                        (function handler(req, res, next) {
                            res.json({ a: 1 })
                            console.log('123456')
                        })()
                    console.log('middleware3 结束')
                })()
            console.log('middleware2 结束')
        })()
    console.log('middleware1 结束')
})

@atian25 加上异步确实是不同了。想深入研究下其中的原理,请问下可以应该看些什么?

@zhuni 为啥我加了异步还是一样,你是怎么加的

想那么多没用,我提个需求,你们实现下就知道了:

  1. 在 middleware A 里面输出一个 result 如 hi, user
  2. 在 middleware 里面获取到前一个的 result,并转化为 json { result: 'hi, user' }再输出。

这才是真实的业务场景。

var express = require('express')
var app = express()

app.use(async function middleware1(req, res, next) {
    console.log('middleware1 开始')
    res.state = await Promise.resolve({ some: 123 })
    next()
    return 2
    console.log('middleware1 结束')
})

app.use(async function middleware2(req, res, next) {
    console.log('middleware2 开始')
    console.log(next)
    console.log(res.state)
    res.state = JSON.stringify(res.state)
    next()
    console.log('middleware2 结束')
})

app.use(function middleware3(req, res, next) {
    console.log('middleware3 开始')
    console.log(typeof res.state)
    next()
    console.log('middleware3 结束')
})

app.get('/', async function(req, res) {
    const ret = await Promise.resolve('Hello World!')
    res.send(ret)
    console.log(ret)
})

app.listen(3000, function() {
    console.log('Example app listening on port 3000!')
})

递归与回调而已,其实把 next 用 promise 包裹一下行了,const handle = async (…args) => next(…args) 就是了

https://nodelover.me/course/middleware/2

koa v1 多了一个执行器co而已 koa v2 async 自带执行器。

@MiYogurt 你这是自己封装了一个约定了。

@atian25 没有,我是说 express 的 next 是回调 不是 promise。 express 也可以异步啊,只要在完成的时候 next 就行。

image.png

它这个包裹就等于

reurn (async () => fn(context, function next () {
return dispatch(i + 1)
})())

@MiYogurt 但 Express 的回调不是洋葱

@atian25 你是不是说的是全局的这种,一个中间件会被全局执行。 express 是基于 layer 的,每次进入 handle 都会拿到匹配的一个然后执行,也就是基于路由的匹配,而 koa 更纯粹,把 router 放在了 中间件上面,而通过 koa-mount 也可以实现类似的。你说的洋葱是这个? 那 express 只能说是有条件的小洋葱。

回到顶部