Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Мой синхронный костыль (https://javascript.ru/forum/project/24115-mojj-sinkhronnyjj-kostyl.html)

FINoM 18.12.2011 05:23

Мой синхронный костыль
 
Продолжаю графоманить. На этот раз предлагаю свой способ поочередного вызова асинхронных функций (таймаутов, анимаций, аяксов и пр.) и избегания ужаса вложенных колбеков.

Для этого вызываем функцию waiting, затем по цепочке вызываем метод wait. Аргументом waiting и wait служит колбек, определенный в примере, как runNext. Его вызов запускает очередную порцию кода.

Для проверки работы откройте консоль.
(function(){
	window.wait = function(first){
		return new (function(){
			var self = this;
			
			var callback = function(){
				var args;
				if(self.deferred.length) {
					args = [].slice.call(arguments);
					args.unshift(callback);
					self.deferred[0].apply(self, args);
					self.deferred.shift();
				}
			}
			
			this.wait = function(run){
				this.deferred.push(run);
				return self;
			}
			
			this.deferred = [];
			
			first(callback);
		})
	}	
	
	/* Пример */
	wait(function(runNext){
		console.log('Run 1');
		setTimeout(function(){
			runNext(1,2); //передаем какие-нибудь аргументы в следующий вызов
		}, 1000);
		
    }).wait(function(runNext, a, b){
		console.log('Run 2, a='+a+' b='+b ); //используем аргументы из предыдущего вызова
        setTimeout(runNext, 1000);
		
    }).wait(function(runNext){
		console.log('Run 3');
        setTimeout(function(){
			console.log('End 3')
			runNext();
		}, 1000);
		
    }).wait(function(runNext){
		console.log('Run 4');
		setTimeout(runNext, 1000);
		
	}).wait(function(){
		console.log('Last one');
		
	});
})();

Пример с анимациями http://jsfiddle.net/finom/XSGub/37/

B~Vladi 20.12.2011 00:56

Что-нибудь можешь прокомментировать по моей идеи?
http://habrahabr.ru/blogs/javascript...omment_4479560

FINoM 20.12.2011 06:33

B~Vladi, то что ты предложил несколько выходит за рамки моих знаний, поэтому компетентного ответа я дать не могу.

B~Vladi 20.12.2011 08:28

Я всё-таки допилю до юзабельного варианта и выложу.

melky 20.12.2011 10:32

не слишком гибко, когда для вызова следующей функции из цепочки обязательно вызывать runNext. конечно, для передачи аргументов в следующий вызов она как раз подходит, но для того, чтобы просто вызвать следующую функцию (99%), потребутся вводить заветные буквы.

возможно ли ту функцию сделать необязательной ? как в этом случае будет обрабатываться время следующего вызова ?

FINoM 20.12.2011 19:28

melky,
А как узнать, что тот же таймаут завершился? Только по коллбеку.
Цитата:

Сообщение от melky
возможно ли ту функцию сделать необязательной ? как в этом случае будет обрабатываться время следующего вызова ?

Ты имеешь в виду, если не указан колбек, то вызывать следующую функцию сразу?

melky 20.12.2011 21:43

да. в этом случае можно указывать параметр, является ли блок кода полностью синхронным, или нет (ajax, напр.). если код async:false (default), если же он async:true - будьте добры тогда указать сами, когда он закончит исполнение (runNext)

FINoM 20.12.2011 22:39

Не знаю есть ли в этом смысл. В любом случае, придется писать
wait(function(){
    this.async = false;
})


вместо
wait(function(){
    this.next();
});

melky 21.12.2011 00:26

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

vflash 21.12.2011 13:36

экспериментировал с подобными штуками . функционал получался такой-же как у вас. Пробовал использовать в практике, но в итоге получается что проще классическим способом написать код или немного поменять алгоритм.

сейчас подумываю упростить. получается что-та вроде цепочки с паузами.


var sync = new ....;

setTimeout(sync(), 1000);
setTimeout(sync(), 100);

sync(function() {

});

setTimeout(sync(), 100);

var xx = sync();
sync(function() {
    ....
    setTimeout(xx, 1000);
    ....
});

sync(function() {

});


Часовой пояс GMT +3, время: 10:32.