1

原文作者:文蔺
原文地址: http://www.wemlion.com/2016/f...
转载请保留此声明。

W3C Draft

题目叫 “Efficient Script Yielding”,一份 2011 年的 “Editor's Draft”,从题目就能看出用途。建议有时间读一遍,超级短。摘要就一句话:

This specification defines an interface for web applications to flush the browser event queue and receive an immediate callback.
本说明文档定义了一个用于刷新浏览器事件队列、接收即时回调的 Web 应用接口。

MDN

MDN 的文档没得说。遇到问题去查查肯定不会害你,有时候运气好,还能读到翻译过来的中文版:

This method is used to break up long running operations and run a callback function immediately after the browser has completed other operations such as events and display updates.
该方法用来把一些需要长时间运行的操作放在一个回调函数里,在浏览器完成后面的其他语句后,就立刻执行这个回调函数。

但同时,文档提到, 只有 IE 10+ 和 Node.js 0.10+ 实现了该方法。setImmediate 受到了 Gecko 和 Webkit 的 “resistance”(抵制)。建议跟着去看看热闹。

MDN 文档中提到了三种模拟 setImmediate 的方式:postMessageMessageChannelsetTimeout(fn, 0)

setImmediate polyfill

对于 Node 0.9 之前的,使用 process.nextTick 模拟;对于非 IE 10 的现代浏览器,使用 postMessage;对 Web Worker,使用 MessageChannel(这个之后需要关注下);对 IE 6–8,向 html 中插入新的 script 标签,在 onreadystatechange 事件中执行回调;其他浏览器,统一使用 setTimeout(fn, 0) 的形式。

// Don't get fooled by e.g. browserify environments.
if ({}.toString.call(global.process) === "[object process]") {
    // For Node.js before 0.9
    installNextTickImplementation();

} else if (canUsePostMessage()) {
    // For non-IE10 modern browsers
    installPostMessageImplementation();

} else if (global.MessageChannel) {
    // For web workers, where supported
    installMessageChannelImplementation();

} else if (doc && "onreadystatechange" in doc.createElement("script")) {
    // For IE 6–8
    installReadyStateChangeImplementation();

} else {
    // For older browsers
    installSetTimeoutImplementation();
}

Nicholas C. Zakas 的文章

文章很短,但讲得还挺仔细的。作者提到了两点好处:

  • 可以直接在 UI 队列清空后直接插入 JS 任务;

  • 延迟更短,不必等待下一次 timer tick

Edge Demo

通过 250 个数的排序,来对比处理效率。基本原理是,排序时将每一步的交换操作放在回调中,对比排序完成的效率。一共有四种:

  • setTimeout(fn, 15)

  • setTimeout(fn, 4)

  • PostMessage

  • setImmediate

关于前两种的时间间隔问题,建议直接取读 demo 底部的说明。已经很详细了。


文蔺
2.3k 声望127 粉丝

前端开发一枚