乐趣区

关于javascript:浏览器与Nodejs中的事件环

浏览器中的事件环,残缺事件环执行程序

  • 从上至下执行所有同步代码
  • 执行过程中遇到的宏工作与微工作增加至相应的队列
  • 同步代码执行结束后,执行满足条件的微工作回调。
  • 微工作队列执行结束后执行所有满足需要的宏工作回调
  • 循环事件环操作
  • 每执行一个宏工作之后就会立即查看微工作队列
setTimeout(() => {console.log("s1");
  Promise.resolve().then(() => {console.log("p1");
  });
  Promise.resolve().then(() => {console.log("p2");
  });
});

setTimeout(() => {console.log("s2");
  Promise.resolve().then(() => {console.log("p3");
  });
  Promise.resolve().then(() => {console.log("p4");
  });
});

// 打印
s1
p1
p2
s2
p3
p4

Node.js 下的事件环

  • timers: 执行 setTimeout 与 setInterval 回调
  • pending callbacks: 执行零碎操作的回调,例如 tcp udp
  • idle,prepare: 只在零碎外部进行应用
  • poll: 执行与 IO 相干的回调
  • check: 执行 setImmediate 中的回调
  • close callbacks: 执行 close 事件的回调
  • 执行同步代码,将不同的工作增加至相应的队列
  • 所有同步代码执行后回去执行满足条件微工作
  • 所有微工作代码执行后会执行 timer 队列中满足的宏工作
  • timer 中的所有宏工作执行实现后就会顺次切换队列
  • 在实现队列切换之前会先清空微工作代码

案例代码

setTimeout(() => {console.log("s1");
});

Promise.resolve().then(() => {console.log("p1");
});

console.log("start");

process.nextTick(() => {console.log("tick");
});

setImmediate(() => {console.log("setimmediate");
});

console.log("end");

打印
start
end
tick
p1
s1
setimmediate

// 1,setTimeout 存入 timer 中
// 2,promise 进入微工作队列
// 3, 输入 start
// 4,nextTick 进入微工作队列
// 5,setImmediate 进入 check 队列中
// 6,输入 end
// 7,微工作中的 tick 优先级高于 promise,先输入 tick,后输入 p1
// 8, 查看 timer,输入 s1
// 9,查看 poll,poll 为空,查看 check
// 10,输入 check 中 setimmediate

setTimeout(() => {console.log("s1");
  Promise.resolve().then(() => {console.log("p1");
  });
  process.nextTick(() => {console.log("t1");
  });
});

Promise.resolve().then(() => {console.log("p2");
});

console.log("start");

setTimeout(() => {console.log("s2");
  Promise.resolve().then(() => {console.log("p3");
  });
  process.nextTick(() => {console.log("t2");
  });
});

console.log("end");
打印
start
end
p2
s1
t1
p1
s2
t2
p3

nodejs 与浏览器事件环差别

  • 工作队列数不同,浏览器只有两个队列,nodejs 中有 6 个事件队列
  • 微工作执行机会不同,二者都会在同步代码执行完之后执行微工作,浏览器平台下每当一个宏工作执行结束后就清空微工作,nodejs 平台在事件队列切换时会去清空微工作。
  • 微工作优先级不同,浏览器事件环中,微工作寄存于事件队列,先进先出,Nodejs 中的 process.nextTick 先于 promise.then

Nodejs 事件环常见问题

setTimeout(() => {console.log("timeout");
},0);

setImmediate(() => {console.log("immdieate");
});

疾速执行时,他们的打印程序可能会替换,setTimeout 与 setImmediate 执行随机,setTimeout 有延时。

const fs = require("fs");
fs.readFile("./m1.js", () => {setTimeout(() => {console.log("timeout");
  }, 0);

  setImmediate(() => {console.log("immdieate");
  });
});

在 I / O 操作的回调中,他们的打印程序固定,先打印 immdieate 再打印 timeout。事件环中 I / O 回调在 poll 队列中执行之后查看微工作队列后切换到 check 中执行 setImmediate,才会切换到 timer 中执行 setTimeout

退出移动版