gpt4 book ai didi

javascript - setTimeout(0) vs window.postMessage vs MessagePort.postMessage

转载 作者:太空狗 更新时间:2023-10-29 15:50:27 34 4
gpt4 key购买 nike

显然,使用 window.postMessagepreferred way在所有现代浏览器中通过 window.setTimeout(fn, 0) 对异步 javascript 回调进行排队。我找不到 window.postMessage 之间的类似比较和 MessagePort.postMessage (使用相同的 MessageChannel 异步发送和接收消息)。有没有人看过或做过任何计时?是否MessagePort.postMessage是否为此目的而工作(如有)?

[EDITED] MessagePort.postMessage 确实适用于此,但 window.postMessage 仍然是首选方式,IMO(请参阅我的回答) .

最佳答案

[更新] 添加了 setImmediate 的测试和一个 JSFiddle 。相关的,有一个cross-browser implementation setImmediateASAP libraryQ 使用 promise 解决/拒绝。

我继续使用 David Baron's code 的修改版本做了一些计时,结果如下:

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

IE10:

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

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),应尽可能避免。

代码:

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

关于javascript - setTimeout(0) vs window.postMessage vs MessagePort.postMessage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18826570/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com