Посоветуйте, какой из вариантов реализации
setImmediate выбрать для асинхронного вызова функций?
Первый вариант:
var callAsync = function () {
var fakeNode = document.createElement("img"), storage = {}, uid = 0;
fakeNode.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
fakeNode.style.cssText = "position: absolute; top: -9999px; left: -9999px; width: 0; height: 0;";
document.body.appendChild(fakeNode);
fakeNode.addEventListener("load", function (event) {
var key = event.key, data = storage[key];
data.callback.call(data.thisObj, data.data);
delete storage[key];
});
return function (callback, thisObj, data) {
var key = "call" + uid++;
storage[key] = {
data: data,
thisObj: thisObj,
callback: callback
};
var event = document.createEvent("HTMLEvents");
event.initEvent("load", false, false);
event.key = key;
fakeNode.dispatchEvent(event);
};
}();
callAsync(function () {
throw Error("test");
});
alert("done");
В этом варианте, мне не нравится, что лишний <img> будет все время находится на странице, попадать в коллекции или мешать какому-нибудь nth-child. А если кому-нибудь вздумается скрипт в <head> засунуть, то придется еще и DOMContentLoaded добавлять для всего, что будет использовать callAsync.
Второй вариант:
var message = "ServiceMessage", storage = {}, uid = 0;
addEventListener("message", function (event) {
var key = event.data, data;
if (typeof key == "string" && key.indexOf(message) == 0) {
data = storage[key];
data.callback.call(data.thisObj, data.data);
delete storage[key];
}
});
function callAsync(callback, thisObj, data) {
var key = message + uid++;
storage[key] = {
data: data,
thisObj: thisObj,
callback: callback
};
postMessage(key, "*");
}
callAsync(function () {
throw Error("test");
});
alert("done");
В этом варианте боюсь, что постоянный флуд в message кому-нибудь навредит.
Третий вариант с использованием setTimeout не рассматриваю, так как не устраивает скорость выполнения.