ФÑнкÑиÑ, оÑÐ»Ð¾Ð¶ÐµÐ½Ð½Ð°Ñ ÑеÑез setTimeout(..0) вÑполниÑÑÑ Ð½Ðµ Ñанее ÑледÑÑÑего «Ñика» ÑаймеÑа, минималÑÐ½Ð°Ñ ÑаÑÑоÑа коÑоÑого Ð¼Ð¾Ð¶ÐµÑ ÑоÑÑавлÑÑÑ Ð¾Ñ 4 до 1000 мÑ. Ð, конеÑно же, ÑÑо пÑоизойдÑÑ Ð¿Ð¾Ñле Ñого, как вÑе ÑекÑÑие Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑдÑÑ Ð¿ÐµÑеÑиÑованÑ.
Ðо нÑжна ли нам ÑÑа дополниÑелÑÐ½Ð°Ñ Ð·Ð°Ð´ÐµÑжка? Ðак пÑавило, иÑполÑзÑÑ setTimeout(func, 0), Ð¼Ñ Ñ
оÑим пеÑенеÑÑи вÑполнение func на «ближайÑее вÑÐµÐ¼Ñ Ð¿Ð¾Ñле ÑекÑÑего кода», и какаÑ-Ñо дополниÑелÑÐ½Ð°Ñ Ð·Ð°Ð´ÐµÑжка нам не нÑжна. ÐÑли Ð±Ñ Ð±Ñла нÑжна â Ð¼Ñ Ð±Ñ ÐµÑ Ñказали вÑоÑÑм аÑгÑменÑом вмеÑÑо 0.
ÐеÑод setImmediate(func)
ÐÐ»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð¿Ð¾ÑÑавиÑÑ ÑÑнкÑÐ¸Ñ Ð² оÑеÑÐµÐ´Ñ Ð½Ð° вÑполнение без задеÑжки, в Microsoft пÑедложили меÑод setImmediate(func). Ðн Ñеализован в IE10+ и на плаÑÑоÑме Node.JS.
У setImmediate единÑÑвеннÑй аÑгÑÐ¼ÐµÐ½Ñ â ÑÑо ÑÑнкÑиÑ, вÑполнение коÑоÑой нÑжно запланиÑоваÑÑ.
РдÑÑгиÑ
бÑаÑзеÑаÑ
setImmediate неÑ, но его можно ÑмÑлиÑоваÑÑ, иÑполÑзÑÑ, к пÑимеÑÑ, меÑод postMessage, пÑедназнаÑеннÑй Ð´Ð»Ñ Ð¿ÐµÑеÑÑлки ÑообÑений Ð¾Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ окна дÑÑгомÑ. ÐеÑали ÑабоÑÑ Ñ postMessage Ð²Ñ Ð½Ð°Ð¹Ð´ÑÑе в ÑÑаÑÑе ÐбÑение окон Ñ ÑазнÑÑ
доменов: postMessage. ÐелаÑелÑно ÑиÑаÑÑ ÐµÑ Ð¿Ð¾Ñле оÑÐ²Ð¾ÐµÐ½Ð¸Ñ ÑÐµÐ¼Ñ Â«Ð¡Ð¾Ð±ÑÑиÑ».
ÐолиÑил Ð´Ð»Ñ setImmediate ÑеÑез postMessage:
if (!window.setImmediate) window.setImmediate = (function() {
var head = { }, tail = head; // оÑеÑÐµÐ´Ñ Ð²Ñзовов, 1-ÑвÑзнÑй ÑпиÑок
var ID = Math.random(); // ÑникалÑнÑй иденÑиÑикаÑоÑ
function onmessage(e) {
if(e.data != ID) return; // не наÑе ÑообÑение
head = head.next;
var func = head.func;
delete head.func;
func();
}
if(window.addEventListener) { // IE9+, дÑÑгие бÑаÑзеÑÑ
window.addEventListener('message', onmessage);
} else { // IE8
window.attachEvent( 'onmessage', onmessage );
}
return function(func) {
tail = tail.next = { func: func };
window.postMessage(ID, "*");
};
}());
ÐÑÑÑ Ð¸ более ÑложнÑе ÑмÑлÑÑии, вклÑÑÐ°Ñ MessageChannel Ð´Ð»Ñ ÑабоÑÑ Ñ Web Workers и Ñ
иÑÑÑй меÑод Ð´Ð»Ñ Ð¿Ð¾Ð´Ð´ÐµÑжки IE8-: https://github.com/NobleJS/setImmediate. ÐÑе они по ÑÑÑеÑÑÐ²Ñ ÑвлÑÑÑÑÑ Â«Ñ
аками», напÑавленнÑми на Ñо, ÑÑÐ¾Ð±Ñ Ð¾Ð±ÐµÑпеÑиÑÑ Ð¿Ð¾Ð´Ð´ÐµÑÐ¶ÐºÑ setImmediate в ÑеÑ
бÑаÑзеÑаÑ
, где его неÑ.
ТеÑÑ Ð¿ÑоизводиÑелÑноÑÑи
ЧÑÐ¾Ð±Ñ ÑÑавниÑÑ ÑеалÑнÑÑ ÑаÑÑоÑÑ ÑÑабаÑÑÐ²Ð°Ð½Ð¸Ñ â измеÑим вÑÐµÐ¼Ñ Ð½Ð° 100 поÑледоваÑелÑнÑÑ
вÑзовов пÑи setTimeout(..0) по ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ñ setImmediate:
if (!window.setImmediate) window.setImmediate = (function() {
var head = {},
tail = head; // оÑеÑÐµÐ´Ñ Ð²Ñзовов, 1-ÑвÑзнÑй ÑпиÑок
var ID = Math.random(); // ÑникалÑнÑй иденÑиÑикаÑоÑ
function onmessage(e) {
if (e.data != ID) return; // не наÑе ÑообÑение
head = head.next;
var func = head.func;
delete head.func;
func();
}
if (window.addEventListener) { // IE9+, дÑÑгие бÑаÑзеÑÑ
window.addEventListener('message', onmessage);
} else { // IE8
window.attachEvent('onmessage', onmessage);
}
return function(func) {
tail = tail.next = {
func: func
};
window.postMessage(ID, "*");
};
}());<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="setImmediate.js"></script>
</head>
<body>
<button onclick="testTimeout()">testTimeout</button>
<button onclick="testImmediate()">testImmediate</button>
<script>
function testTimeout() {
var start = new Date();
var i = 0;
setTimeout(function go() {
i++;
if (i == 100) {
alert(new Date - start);
} else {
setTimeout(go, 0);
}
}, 0);
}
function testImmediate() {
var start = new Date();
var i = 0;
setImmediate(function go() {
i++;
if (i == 100) {
alert(new Date - start);
} else {
setImmediate(go);
}
});
}
</script>
</body>
</html>ÐапÑÑÑиÑе пÑÐ¸Ð¼ÐµÑ Ð²ÑÑе â и Ð²Ñ ÑвидиÑе ÑеалÑнÑÑ ÑазниÑÑ Ð²Ð¾ вÑемени Ð¼ÐµÐ¶Ð´Ñ setTimeout(.., 0) и setImmediate. Ðа, она Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð±Ð¾Ð»ÐµÐµ в 50, 100 и более Ñаз.
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)