admin管理员组文章数量:1313798
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 parison 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)?
[EDITED] MessagePort.postMessage
does work for this, but window.postMessage
remains a preffered way, IMO (see my answer).
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 parison 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)?
[EDITED] MessagePort.postMessage
does work for this, but window.postMessage
remains a preffered way, IMO (see my answer).
-
As this still gets views... check out
queueMicrotask
. – noseratio Commented Oct 20, 2021 at 0:13
1 Answer
Reset to default 8[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.
I went ahead and did some timing, using a modified version of David Baron's code, the results are below:
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.
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.
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./q/18826570/1768303 -->
<!-- based on http://dbaron/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>
本文标签: javascriptsetTimeout(0) vs windowpostMessage vs MessagePortpostMessageStack Overflow
版权声明:本文标题:javascript - setTimeout(0) vs window.postMessage vs MessagePort.postMessage - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741911724a2404482.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论