Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 19.03.2014, 17:21
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Асинхронный вызов функций
Посоветуйте, какой из вариантов реализации 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 не рассматриваю, так как не устраивает скорость выполнения.

Последний раз редактировалось Octane, 23.03.2014 в 14:59.
Ответить с цитированием
  #2 (permalink)  
Старый 19.03.2014, 18:01
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Сообщение от Octane
Третий вариант с использованием setTimeout не рассматриваю, так как не устраивает скорость выполнения.
поясни

http://stackoverflow.com/a/9516967
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #3 (permalink)  
Старый 19.03.2014, 18:39
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Сообщение от nerv_
поясни
у setTimeout есть минимальная задержка 3-5 мс, передавать 0 бесполезно
Ответить с цитированием
  #4 (permalink)  
Старый 19.03.2014, 19:00
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Сообщение от Octane
у setTimeout есть минимальная задержка 3-5 мс, передавать 0 бесполезно
это понятно
Если функция вызывается асинхронно, то время, когда именно она будет вызвана может варьироваться и зависит от ряда факторов. О какой скорости может идти речь в этом случае, я не понимаю

В первом варианте заменил alert() на console.log(), в хроме получилось синхронно.
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #5 (permalink)  
Старый 19.03.2014, 19:04
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Тесты на скорость выполнения:

var intervals = [], i = 100, t1 = Date.now(), t2;

setTimeout(function () {

	t2 = Date.now();

	intervals.push(t2 - t1);

	t1 = t2;

	if (i--) {
		setTimeout(arguments.callee, 0);
	}
	else {
		alert(intervals);
	}

}, 0);



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, "*");
}

var intervals = [], i = 100, t1 = Date.now(), t2;

callAsync(function () {

	t2 = Date.now();

	intervals.push(t2 - t1);

	t1 = t2;

	if (i--) {
		callAsync(arguments.callee);
	}
	else {
		alert(intervals);
	}

});

Последний раз редактировалось Octane, 23.03.2014 в 15:00.
Ответить с цитированием
  #6 (permalink)  
Старый 29.03.2014, 01:17
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Еще ссылки

setImmediate
The case for setImmediate()
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #7 (permalink)  
Старый 30.03.2014, 04:11
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Есть идеи, почему у первого варианта в IE8 длина стека вызовов всего 5?

/**
 * setImmediate polyfill
 */
window.setImmediate || new function () {

	var id = 0, storage = {}, message = "setImmediatePolyfillMessage";

	function fastApply(args) {
		var func = args[0];
		switch (args.length) {
			case 1: return func();
			case 2: return func(args[1]);
			case 3: return func(args[1], args[2]);
		}
		return func.apply(window, Array.slice(args, 1));
	}

	function callback(event) {
		var key, data;
		event = event || window.event;
		key = event.data;
		if (typeof key == "string" && key.startsWith(message)) {
			data = storage[key];
			if (data) {
				fastApply(data);
				delete storage[key];
			}
		}
	}

	function setImmediate() {
		var key = message + ++id;
		storage[key] = arguments;
		postMessage(key, "*");
		return id;
	}

	function clearImmediate(id) {
		delete storage[message + id];
	}

	addEventListener("message", callback, false);

	window.setImmediate = setImmediate;
	window.clearImmediate = setImmediate;

};

пробовал arguments преобразовывать в массив, не помогает, 6-й рекурсиный вызов приводит к stack overflow

/**
 * IE8 setImmediate polyfill
 */
document instanceof Object || new function () {

	var root = document.documentElement, fakeScript = document.createElement("script");

	//todo code reuse
	function fastApply(args) {
		var func = args[0];
		switch (args.length) {
			case 1: return func();
			case 2: return func(args[1]);
			case 3: return func(args[1], args[2]);
		}
		return func.apply(window, Array.slice(args, 1));
	}

	function setImmediate () {
		var args = arguments, tmpScript = fakeScript.cloneNode(false);
		tmpScript.onreadystatechange = function () {
			fastApply(args);
			tmpScript.onreadystatechange = null;
			root.removeChild(tmpScript);
			tmpScript = null;
		};
		root.appendChild(tmpScript);
		return 0;
	}

	function clearImmediate() {}

	window.setImmediate = setImmediate;
	window.clearImmediate = setImmediate;

};
а этот вариант нормально работает
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как в функции объявить вызов других функций, еще не определенных? lonleystranger Общие вопросы Javascript 6 26.11.2013 11:16
XMLHttpRequest асинхронный вызов. Loki6999 Общие вопросы Javascript 2 16.10.2013 09:56
Вызов локальной функций внутри переменной gibigate Общие вопросы Javascript 1 20.03.2013 14:47
Асинхронный вызов толстых функций Rogov Dmitry Events/DOM/Window 15 02.08.2011 14:11
Вызов функций iframe из кода Firefox-расширения Jury Firefox/Mozilla 0 03.05.2011 13:09