Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 16.10.2011, 18:28
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Упрощенный Deferred
Примерно тоже самое находиться в jQuery и Dojo, но здесь сильно упрощенный вариант (не продумана вероятность ошибок в обработчиках, нельзя указать контекст выполнения обработчиков и т. д.). Предназначен, чтобы разобраться, как это работает на простом примере и/или для допиливания (выкладывайте прямо здесь, что получается). Критика приветствуется.

/**
 * Id: deferred
 * */

(function() {

var arraySlice = [].slice;

function Deferred() {
	if (!(this instanceof Deferred)) {
		throw new TypeError();
	}
	this._then = [];
	this.then.apply(this, arguments);
}

Deferred.prototype = {
	_resolved: false,

	then: function _(callback) {
		if (callback) {
			if (this._resolved) {
				callback();
			} else {
				this._then.push(callback);
			}
		}
		if (arguments.length > 1) {
			_.apply(this, arraySlice.call(arguments, 1));
		}
		return this;
	},

	resolve: function() {
		if (!this._resolved) {
			this._resolved = true;
			var results = [], then = this._then, i = 0, l = then.length;
			while (i < l) {
				results[i] = then[i++].apply(null, arguments);
			}
			return results;
		}
	}
};

Deferred.when = function() {
	var dfr = new Deferred(), count = 0;
	function resolveFunc() {
		if (!--count) {
			dfr.resolve();
		}
	}
	for (var i = 0, l = arguments.length; i < l; ++i) {
		if (arguments[i]) {
			++count;
			arguments[i].then(resolveFunc);
		}
	}
	return dfr;
};

this.Deferred = Deferred;

})();

// пример использования:
var dfr1 = new Deferred(function() { console.log('dfr 1'); });
var dfr2 = new Deferred(function() { console.log('dfr 2'); });

Deferred.when(dfr1, dfr2).then(function() { console.log('dfr all'); });

setTimeout(function() { dfr1.resolve(); }, 2000);
setTimeout(function() { dfr2.resolve(); }, 5000);


UPD: полезные ссылки: 1, 2, 3, 4, 5.

Последний раз редактировалось Riim, 16.10.2011 в 18:40.
Ответить с цитированием
  #2 (permalink)  
Старый 17.10.2011, 10:22
Профессор
Отправить личное сообщение для tenshi Посмотреть профиль Найти все сообщения от tenshi
 
Регистрация: 20.03.2008
Сообщений: 1,183

а слабо разобраться в этой штуке? ;-) http://forum.mozilla-russia.org/viewtopic.php?id=51812
__________________
.ня
Ответить с цитированием
  #3 (permalink)  
Старый 17.10.2011, 15:23
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от tenshi
а слабо разобраться в этой штуке?
это что-то вроде этого: http://softwaremaniacs.org/blog/2009/12/11/adisp/ ?
Ответить с цитированием
  #4 (permalink)  
Старый 18.10.2011, 00:48
Профессор
Отправить личное сообщение для tenshi Посмотреть профиль Найти все сообщения от tenshi
 
Регистрация: 20.03.2008
Сообщений: 1,183

угу, только с поддержкой исключений и на яваскрипте
__________________
.ня
Ответить с цитированием
  #5 (permalink)  
Старый 29.10.2011, 03:23
Аватар для float
Профессор
Отправить личное сообщение для float Посмотреть профиль Найти все сообщения от float
 
Регистрация: 01.07.2010
Сообщений: 387

для своего велосипеда сделал диферд следующей структуры:

var d = _.deferred() - создаёт объект. в моей реализации это типо суперкласс.
d.stage('ajax') - создаёт стадию.
таких стадий может быть сколько угодно.
их можно:
d.resolve('ajax')
d.reject('ajax')
d.stage('ajax').done(function() {...}).fail(function() {...});
ещё может передаваться контекст и параметры, можно выполнять без имени, тогда завершиться следующая стадия в очереди.
если в d не осталось незавершённых стадий, он сам завершается, тут 3 варианта:
success (все стадии resolve)
err (хоть одна reject)
anyway

вроде всё...

Как задумка?
сам как написал, сел задумался: какая же х*рня. какое-то масло масляное(у меня ещё when есть). и тд и тп.
но решил оставить.
уже пару раз, с удивлением, словил себя на мысли, когда юзал его, мол "вау. так пригодилось, а я о таком даже не подумал".
но чёт до сих пор сомневаюсь...

Последний раз редактировалось float, 29.10.2011 в 03:35.
Ответить с цитированием
  #6 (permalink)  
Старый 29.10.2011, 05:01
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

я правильно понял, что на каждую созданную стадию, вы можете навешивать свои собственные обработчики, и вызывать их обработку для конкретной стадии?
По-сути, можно заменить массивом независимых Deferred, каждый из которых представляет свое состояние?

Если да, то в чем смысл/польза?
Если нет, то прошу пояснить подробнее идею. желательно с примерами, где она гармонично у вас вписывается
Ответить с цитированием
  #7 (permalink)  
Старый 29.10.2011, 13:52
Аватар для float
Профессор
Отправить личное сообщение для float Посмотреть профиль Найти все сообщения от float
 
Регистрация: 01.07.2010
Сообщений: 387

Да, правильно.
Цитата:
По-сути, можно заменить массивом независимых Deferred
да можно.

Смысл/польза в том, что свой велосипед юзаю в риа. и там случаев, где надо делать массив больше, нежели где надо простой диферд.

Код писал под пример(тоесть сначала написал пример, а потом код для реализации).
Тут могут быть эм-ты фреймворка если что.

var d = _.deferred();

// ##### --- stages actions

d.stage('animation').done(function() {
		console.log('animation finished');
	}).fail(function() {
		console.log('animation failed');
	});

d.stage('ajax').done(function() {
		console.log('ajax done');
	}).fail(function() {
		console.log('ajax fail');
	});

d.stage('button');

// ##### --- actions

_.post('some/url.php').succes(function(data) {
	d.resolve('ajax', data);
}).err(function(err) {
	d.reject('ajax', err);
});

_('.menu').hide(200, function() {
	if(this.length) {
		d.resolve('animation');
	}
	else {
		d.reject('animation');
	}
});

_('.button-forward').click(function() {
	d.resolve('button');
});
_('.button-back').click(function() {
	d.reject('button');
});

// ##### --- defered finally

d.success(function() {
	console.log('chain success');
}).anyway(function() {
	console.log('chain done');
}).err(function() {
	console.log('chain with err');
});


Вот. Я было попробовал это переписать короче - не получилось...
Ещё из плюсов:
не засирается область лишними переменными.

+я изначально диферд сделал простым. тоесть все свойства создаются в момент навешивания обработчиков.
так что можно не париться что колбасу режем скальпелем.

Последний раз редактировалось float, 29.10.2011 в 14:02.
Ответить с цитированием
  #8 (permalink)  
Старый 29.10.2011, 14:13
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

судя по последним строчкам вы сделали DeferredList, который позволяет обращаться через себя к отдельным Deferred
Плюс добавление наблюдаемых объектов на лету.

Вопрос на засыпку: что будет, если я после d.success() добавлю, а позже выполню еще одну стадию?
сработает ли еще раз d.success с дополниельной стадией?
Ответить с цитированием
  #9 (permalink)  
Старый 29.10.2011, 14:26
Аватар для float
Профессор
Отправить личное сообщение для float Посмотреть профиль Найти все сообщения от float
 
Регистрация: 01.07.2010
Сообщений: 387

Цитата:
с дополниельной стадией?
ща проверил. нет не срабатывает.
то есть после выполнения диферда на него можно навешать ещё стадий. и выполнять их. но обраьботчики на дифферде сработают только 1 раз.
признаться про это я не думал, когда делал(ну или мб забыл, ночь всё таки была).

Цитата:
DeferredList
ну не совсем.
я забыл упомянуть, что и у самого диферда есть d.finish().
тоесть его самого можно юзать как простейший $диферд.
d.anyway(function() {...}).anyway(function() {...}).anyway(function() {...});
d.finish();

В общем АД

Последний раз редактировалось float, 29.10.2011 в 14:32.
Ответить с цитированием
  #10 (permalink)  
Старый 29.10.2011, 14:30
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

Сообщение от float
нет не срабатывает.
ну, значит нормально

Сообщение от float
я забыл упомянуть, что и у самого диферда есть d.finish().
что он делает?
resolve-ит все объявленные стадии и глобальный обработчик?
Ответить с цитированием
Ответ



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

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