Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/420.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript setTimeout(0)vs window.postMessage vs MessagePort.postMessage_Javascript_Html_Asynchronous_Timeout_Message - Fatal编程技术网

Javascript setTimeout(0)vs window.postMessage vs MessagePort.postMessage

Javascript setTimeout(0)vs window.postMessage vs MessagePort.postMessage,javascript,html,asynchronous,timeout,message,Javascript,Html,Asynchronous,Timeout,Message,显然,在所有现代浏览器中,都可以使用is将异步javascript回调在window.setTimeout(fn,0)上排队。我在和之间找不到类似的比较(使用相同的方法异步发送和接收消息)。有人看到或做过任何计时吗?是否适用于此目的(如有) [编辑]MessagePort.postMessage确实适用于此,但窗口。postMessage仍然是首选方式,IMO(请参见我的答案)。[更新]添加了一个测试和一个。相关的,有一个ofsetImmediate,用于承诺解决/拒绝 我继续进行了一些计时,使

显然,在所有现代浏览器中,都可以使用is将异步javascript回调在
window.setTimeout(fn,0)
上排队。我在和之间找不到类似的比较(使用相同的方法异步发送和接收消息)。有人看到或做过任何计时吗?是否适用于此目的(如有)


[编辑]
MessagePort.postMessage
确实适用于此,但
窗口。postMessage
仍然是首选方式,IMO(请参见我的答案)。

[更新]添加了一个测试和一个。相关的,有一个of
setImmediate
,用于承诺解决/拒绝

我继续进行了一些计时,使用的是的修改版本,结果如下:

setTimeoutMC
-使用
MessageChannel

setTimeoutPM
-使用
window.postMessage

setTimeout(0)
-使用
setTimer

IE10:

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.
很明显,这是赢家(考虑到现有的跨浏览器支持水平)。较松的是
窗口。设置超时(fn,0)
,应尽可能避免

代码:

<!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>

//通过MessageChannel设置TimeOutMC
(功能(){
“严格使用”;
var i=0;
var超时={};
var setApiName=“setTimeoutMC”;
var clearApiName=“clearTimeoutMC”;
var channel=newmessagechannel();
职能职位(fn){
if(i==0x100000000)//最大队列大小
i=0;
如果(++i输入超时)
抛出新错误(setApiName+“队列溢出”);
超时时间[i]=fn;
通道端口2.后消息(i);
返回i;
}
channel.port1.onmessage=函数(ev){
var id=ev数据;
var fn=超时[id];
如果(fn){
删除超时[id];
fn();
}
}
功能清除(id){
删除超时[id];
}
channel.port1.start();
channel.port2.start();
window[setApiName]=post;
窗口[clearApiName]=清除;
})();
//通过window.postMessage设置时间输出
(功能(){
“严格使用”;
var i=0;
var超时={};
var setApiName=“setTimeoutPM”;
var clearApiName=“clearTimeoutPM”;
var messageName=setApiName+new Date().getTime();
职能职位(fn){
if(i==0x100000000)//最大队列大小
i=0;
如果(++i输入超时)
抛出新错误(setApiName+“队列溢出”);
超时时间[i]=fn;
postMessage({type:messageName,id:i},“*”);
返回i;
}
功能接收(ev){
如果(ev.source!==窗口)
返回;
var数据=ev数据;
if(对象的数据和数据实例&&data.type===messageName){
ev.stopPropagation();
var id=ev.data.id;
var fn=超时[id];
如果(fn){
删除超时[id];
fn();
}
}
}
功能清除(id){
删除超时[id];
}
window.addEventListener(“消息”,接收,真);
window[setApiName]=post;
窗口[clearApiName]=清除;
})();
//时机
函数runtest(){
var output=document.getElementById(“输出”);
var outputText=document.createTextNode(“”);
appendChild(outputText);
函数打印输出(行){
outputText.data+=行+“\n”;
}
var n=2000;
var i=0;
var startTime=Date.now();
setTimeoutMC(testMC);
函数testMC(){
如果(++i==n){
var endTime=Date.now();
printOutput(setTimeoutMC的n+“迭代花费”+(endTime-startTime)+“毫秒”);
i=0;
startTime=Date.now();
setTimeoutPM(testPM,0);
}否则{
setTimeoutMC(testMC);
}
}
函数testPM(){
如果(++i==n){
var endTime=Date.now();
printOutput(setTimeoutPM的n+“迭代花费”+(endTime-startTime)+“毫秒”);
i=0;
startTime=Date.now();
设置超时(测试,0);
}否则{
setTimeoutPM(testPM);
}
}
功能测试(){
如果(++i==n){
var endTime=Date.now();
printOutput(setTimeout(0)的n+次迭代花费了“+(endTime-startTime)+”毫秒);
}
否则{
设置超时(测试,0);
}
}
}

在支持Promise的浏览器上(据统计,Promise是大多数主流浏览器),Promise.resolve可能会更快。请参阅my,在我的测试中,最新的Firefox夜间构建速度提高了5-6倍。@MykMelez哇。对本地人的承诺很好!为什么设置超时不能那么快?有什么原因吗?setTimeout也可以替换为Promise.resolve实现,但这会导致问题吗
<!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>