上次写Stream pipe细节时,在源码中发现一段无用逻辑,由此引发了对Stream data事件触发时机与顺序的探索。
无用逻辑
当时研究pipe细节是基于Node.js v8.11.1的源码,其中针对上游的ondata事件处理有如下一段代码:
// If the user pushes more data while we're writing to dest then we'll end up
// in ondata again. However, we only want to increase awaitDrain once because
// dest will only emit one 'drain' event for the multiple writes.
// => Introduce a guard on increasing awaitDrain.
var increasedAwaitDrain = false;
src.on('data', ondata);
function ondata(chunk) {
debug('ondata');
increasedAwaitDrain = false;
var ret = dest.write(chunk);
if (false === ret && !increasedAwaitDrain) {
if (((state.pipesCount === 1 && state.pipes === dest) ||
(state.pipesCount > 1 && state.pipes.indexOf(dest) !== -1)) &&
!cleanedUp) {
debug('false write response, pause', src._readableState.awaitDrain);
src._readableState.awaitDrain++;
increasedAwaitDrain = true;
}
src.pause();
}
}重点关注
increasedAwaitDrain变量,理解这个变量期望达到什么目的,然后仔细阅读代码,会发现
if (false === ret && !increasedAwaitDrain)语句中
increasedAwaitDrain变量肯定是false,因为前一行才将该变量赋值为false,这样一来这个变量就变得毫无意义。
increasedAwaitDrain = false;
var ret = dest.write(chunk);
if (false === ret && !increasedAwaitDrain) {}以上就是关键的三行代码,因为Node.js是单线程且
dest.write(chunk)内部没有修改变量
increasedAwaitDrain的值,那么if语句中
increasedAwaitDrain的值肯定还是false,即
increasedAwaitDrain相关逻辑没有达到所期望的目标。无用代码出现的原因
前段虽已经分析出
increasedAwaitDrain没起到作用,但作者为什么写了这样一段逻辑呢?其实在定义
increasedAwaitDrain语句的上方,作者说可能存在这样一种情况:“当我们接收到一次上游的ondata事件并尝试将数据写到下游时,上游可能同时又有一个data事件触发,而这两个ondata的数据在写入下游时可能都返回false,从而导致
src._readableState.awaitDrain++执行两次”。









