的setTimeout(0)与window.postMessage VS MessagePort.postMessage [英] setTimeout(0) vs window.postMessage vs MessagePort.postMessage

查看:203
本文介绍了的setTimeout(0)与window.postMessage VS MessagePort.postMessage的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

显然,使用 window.postMessage 是一个 preferred方式排队一个异步JavaScript回调超过 window.setTimeout(FN,0)在所有现代浏览器。我找不到窗口之间的类似的比较.postMessage MessagePort。 postMessage的(使用相同 MessageChannel 的发送和接收异步消息)。有没有人见过或做任何时机? MessagePort.postMessage 工作为此,在所有(如果有的话)?

Apparently, using window.postMessage is a preferred way to queue an async javascript callback over window.setTimeout(fn, 0) across all modern browsers. I could not find a similar comparison between window.postMessage and MessagePort.postMessage (using the same MessageChannel for sending and receiving messages asynchronously). Has anyone seen or done any timing? Does MessagePort.postMessage work for this purpose at all (where available)?

MessagePort.postMessage 做这项工作,但 window.postMessage 仍然是preffered方式,国际海事组织(见我回答)。

MessagePort.postMessage does work for this, but window.postMessage remains a preffered way, IMO (see my answer).

推荐答案

[更新] 增加了的 setImmediate 的jsfiddle 。相关的,还有 setImmediate 跨浏览器实现并通过的尽快库 =nofollow的>问:的承诺分辨率/拒绝。

[UPDATE] Added a test for setImmediate and a JSFiddle. Related, there's a cross-browser implementation of setImmediate and ASAP library used by Q for a promise resolution/rejection.

我继续做了一些时间,使用大卫男爵的code的修改版本< /一>时,结果如下:

I went ahead and did some timing, using a modified version of David Baron's code, the results are below:

setTimeoutMC - 使用 MessageChannel 结果
setTimeoutPM - 使用 window.postMessage 结果
的setTimeout(0) - 使用的SetTimer 搜索

setTimeoutMC - using MessageChannel
setTimeoutPM - using window.postMessage
setTimeout(0) - using setTimer

IE10:

2000 iterations of setTimeoutMC took 126 milliseconds.
2000 iterations of setTimeoutPM took 190 milliseconds.
2000 iterations of setTimeout(0) took 7986 milliseconds.

铬v29.0.1547.66:

Chrome v29.0.1547.66:

2000 iterations of setTimeoutMC took 144 milliseconds.
2000 iterations of setTimeoutPM took 81 milliseconds.
2000 iterations of setTimeout(0) took 10589 milliseconds.

显然, window.postMessage 这里是赢家(考虑为它现有的跨浏览器的支持程度)。较为宽松的是 window.setTimeout(FN,0),应尽可能避免。

Clearly, window.postMessage is the winner here (considering the level of existing cross-browser support for it). The looser is window.setTimeout(fn, 0) and should be avoided wherever possible.

code:

<!DOCTYPE html>
<html>
<head>
    <!-- http://stackoverflow.com/q/18826570/1768303 -->
    <!-- based on http://dbaron.org/log/20100309-faster-timeouts -->
    <!-- requires IE10 or Chrome. Firefox doesn't support MessageChannel yet -->
    <title></title>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <script type="text/javascript">

        // setTimeoutMC via MessageChannel

        (function () {
            "use strict";
            var i = 0;
            var timeouts = {};
            var setApiName = "setTimeoutMC";
            var clearApiName = "clearTimeoutMC";

            var channel = new MessageChannel();

            function post(fn) {
                if (i === 0x100000000) // max queue size
                    i = 0;
                if (++i in timeouts)
                    throw new Error(setApiName + " queue overflow.");
                timeouts[i] = fn;
                channel.port2.postMessage(i);
                return i;
            }

            channel.port1.onmessage = function (ev) {
                var id = ev.data;
                var fn = timeouts[id];
                if (fn) {
                    delete timeouts[id];
                    fn();
                }
            }

            function clear(id) {
                delete timeouts[id];
            }

            channel.port1.start();
            channel.port2.start();

            window[setApiName] = post;
            window[clearApiName] = clear;
        })();

        // setTimeoutPM via window.postMessage

        (function () {
            "use strict";
            var i = 0;
            var timeouts = {};
            var setApiName = "setTimeoutPM";
            var clearApiName = "clearTimeoutPM";
            var messageName = setApiName + new Date().getTime();

            function post(fn) {
                if (i === 0x100000000) // max queue size
                    i = 0;
                if (++i in timeouts)
                    throw new Error(setApiName + " queue overflow.");
                timeouts[i] = fn;
                window.postMessage({ type: messageName, id: i }, "*");
                return i;
            }

            function receive(ev) {
                if (ev.source !== window)
                    return;
                var data = ev.data;
                if (data && data instanceof Object && data.type === messageName) {
                    ev.stopPropagation();
                    var id = ev.data.id;
                    var fn = timeouts[id];
                    if (fn) {
                        delete timeouts[id];
                        fn();
                    }
                }
            }

            function clear(id) {
                delete timeouts[id];
            }

            window.addEventListener("message", receive, true);
            window[setApiName] = post;
            window[clearApiName] = clear;
        })();

        // timing

        function runtest() {
            var output = document.getElementById("output");
            var outputText = document.createTextNode("");
            output.appendChild(outputText);
            function printOutput(line) {
                outputText.data += line + "\n";
            }

            var n = 2000;
            var i = 0;
            var startTime = Date.now();
            setTimeoutMC(testMC);

            function testMC() {
                if (++i === n) {
                    var endTime = Date.now();
                    printOutput(n + " iterations of setTimeoutMC took " + (endTime - startTime) + " milliseconds.");
                    i = 0;
                    startTime = Date.now();
                    setTimeoutPM(testPM, 0);
                } else {
                    setTimeoutMC(testMC);
                }
            }

            function testPM() {
                if (++i === n) {
                    var endTime = Date.now();
                    printOutput(n + " iterations of setTimeoutPM took " + (endTime - startTime) + " milliseconds.");
                    i = 0;
                    startTime = Date.now();
                    setTimeout(test, 0);
                } else {
                    setTimeoutPM(testPM);
                }
            }

            function test() {
                if (++i === n) {
                    var endTime = Date.now();
                    printOutput(n + " iterations of setTimeout(0) took " + (endTime - startTime) + " milliseconds.");
                }
                else {
                    setTimeout(test, 0);
                }
            }
        }
    </script>
</head>

<body onload="runtest()">
    <pre id="output"></pre>
</body>
</html>

这篇关于的setTimeout(0)与window.postMessage VS MessagePort.postMessage的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆