express中间件的问题
发布于 10 年前 作者 keller35 7387 次预览 最后一次回复是 10 年前 来自 问答
开发express中间件的时候遇到一个问题: 代码如下:
app.use(function(req, res, next){ next(); console.log(“after next”); }); app.use(function(req, res, next){ console.log(“before next”); next(); });
这里的中间件调用结果是:
before next after next
所以我认为中间件是一个栈结构,next前的代码先执行,然后执行next调用下一个中间件,最后回到当前的中间件,执行next后面的代码。 但是我写了另外一个例子,并不支持我这种理解。 代码如下:
app.use(function(req, res, next){ next(); console.log(“after next”) }); app.use(function(req, res, next){ process.nextTick(function(){ console.log(“before next”) next(); }); });
执行结果:
after next before next
请问这是什么原因?
11 回复
当前next栈结构只是同步执行的,这里的异步的代码要到等到下次nextTick事件执行,只有一个线程,一次只能执行一个事件
理解nextTick的机制你就明白了
next 是同步的 nextTick 是异步的,也就是会等到当前所有同步操作完成之后才有机会轮到它。
@holyselina 中间件的栈结构也是需要调用next才执行的,而我在异步操作中调用next,按道理也是顺序执行中间件,为什么就不对了,这个地方能解释下吗?
@klesh 嗯,我知道nextTick是异步的,但是我的next也是在异步操作中调用的
@keller35 啊? … 首先,想像虚拟机是一个环回系统,js 代码就一个队例,虚拟机不停地从队例中取出“一段同步”代码。执行,完成后又去队例中取出另一段代码,执行。。。直到队列清空,程序就退出了。当然,每次执行又可能产出新的一段“代码”插入到队列中,这样程序就一直地运行下去。
第一个 next 执行后,是去到 nextTick 对吧,但是所有一切在nexTick中的代码这个时候都不会执行,而是被插入到队例后面。然后程序继续往下走,就执行了 console.log(“after next”)。然后本次“同步”代码全部执行完了,虚拟机进入下一次循环,这时 nextTick 中的代码才会被执行。
@klesh 嗯,谢谢你的回答! 你所说的我都明白,event loop我也理解。 但是我不理解的地方是:next作为下一个中间件的调用函数,需要调用了代码才会执行到下一个中间件。而这里是还未调用next的时候,就先执行了console.log(“after next”)?
@keller35 你……,真的明白吗?哎,next不是未调用,事实上第一个next函数绝对是正常调用了,这时候就转到第二个 use ,其中传给nextTick的函数 不会马上执行,process.nextTick只是把这个函数插入 event loop,而不是马上执行这个函数。插完函数就立即返回了,这个时候就回到第一个 use 中执行 console.log(“after next”)。到了这个点,本次 loop 才完成,之后才会把刚才插入的函数拿出来执行,打印出 before next 。
你把
next()理解错了. express的next()跟koajs的yield next是不一样的…@William17 嗯,谢谢你的回答。 是我把next理解错了,看了你的第二段代码就明白了。 那可否简单说一下koa的next有什么不同?