Показать сообщение отдельно
  #34 (permalink)  
Старый 04.09.2011, 17:43
Отправить личное сообщение для Андрей Параничев Посмотреть профиль Найти все сообщения от Андрей Параничев
 
Регистрация: 21.02.2008
Сообщений: 1,250

dmitriymar,
Я если честно не понимаю, чего вы не поняли и почему утверждаете про синхронность исходя из однопоточности JavaScript, учитывая сколько в этом обсуждении уже написано про это.

Представьте мой пример в таком виде, есть объект и сложное UI, модель которого связана через события с нулевым таймаутом при emit. От пользователя приходят два события, которые имеют сложную обработку, допустим это будет mouseover и mousedown. Допустим, что они произошли практически одновременно. В синхронном коде обработчик mouseover будет выполняться до конца, после этого будет вызван обработчик mousedown. При организации кода через события с асинхронным выполнением произойдет mouseover, будет получен из кода emit, потом обработан mousedown, будет получен emit, потом обработчики, если они будут генерировать новые события и передавать управление с нулевым таймаутом, будут выполняться не последовательно, а в режиме вытесняющей очереди со случайным выбором. Дальнейшие разъяснения нужны?


Для подтверждения моих слов вот вам код. Если бы было все синхронно и просто очередью, до обработчики бы были вызваны в порядке, что алерты были бы такие: 1, 2, 4, 6, 3, 5, 7. Но они будут вызваны в таком порядке: 1, 2, 3, 4, 5, 6, 7. Потому что вызов события не мешает выполнению как-бы другого рута событий.

Поправьте, если я ошибаюсь и это тоже "синхронная" работа:
// Скрипт для работы событий:
var Ev = {
	"__listeners__":  {},

	"EventEmitter": function(object) {
		object.__listeners__       = {};
		object.addEventListener    = object.on = this.addEventListener;
		object.removeEventListener = this.removeEventListener;
		object.getEventListeners   = this.getEventListeners;
		object.clearEventListeners = this.clearEventListeners;
		object.emit                = this.emit;
	},

	"addEventListener": function(eventName, listener) {
		eventName in this.__listeners__ ?
			this.__listeners__[eventName].push(listener) :
			this.__listeners__[eventName] = [listener];

		return listener;
	},

	"removeEventListener": function(eventName, listener) {
		if (eventName in this.__listeners__) {
			for (var i in this.__listeners__[eventName])
			if  (this.__listeners__[eventName].hasOwnProperty(i))
				if (this.__listeners__[eventName][i] === listener)
					this.__listeners__[eventName].splice(i, 1);
		}
	},

	"getEventListeners": function(eventName) {
		if (eventName in this.__listeners__)
			return this.__listeners__[eventName];
	
		return null;
	},

	"emit": function(eventName, eventData) {
		var self = this;
		eventData = eventData || null;
		if (eventName in this.__listeners__) {
			for (var i in this.__listeners__[eventName])
			if  (this.__listeners__[eventName].hasOwnProperty(i)) {
				setTimeout((function(i) { return function() { self.__listeners__[eventName][i](eventData); } })(i), 0);
			}
		}
	}
};

// Какой-то конструктор:
var B = function() {
	var self = this;

	// Добавляем методы событий в наш объект:
	Ev.EventEmitter(this);

	// Подписываемся тремя обработчиками на событие "someEvent":
	this.addEventListener("someEvent", function() {
		self.emit("someEvent2");
		alert(2);
	});

	this.addEventListener("someEvent", function() {
		self.emit("someEvent3");
		alert(3);
	});

	this.addEventListener("someEvent2", function() {
		self.emit("someEvent4");
		alert(4);
	});

	this.addEventListener("someEvent3", function() {
		self.emit("someEvent5");
		alert(5);
	});

	this.addEventListener("someEvent4", function() {
		alert(6);
	});

	this.addEventListener("someEvent5", function() {
		alert(7);
	});
};

// Этот метод генерирует событие "someEvent":
B.prototype.generateEvent = function() {
	alert("Let's start!");
	
	// Генерируем событие:
	this.emit("someEvent");

	// Проверяем, остались ли мы в этом участке кода:
	alert(1);

	// Только теперь должно быть выполнение асинхронных обработчиков.
	return false;
};

// Создаем объект и выполняем метод, генерирующий событие:
b = new B();
b.generateEvent();

Последний раз редактировалось Андрей Параничев, 04.09.2011 в 18:01.
Ответить с цитированием