Тема: Свой Promise
Показать сообщение отдельно
  #1 (permalink)  
Старый 11.08.2017, 11:53
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,791

Свой Promise
Да, велосипед.
Promise описываемый в учебнике мне не понравился.
jQ.deferred не реализовывал желаемого (а может просто руки кривые). Хотелось, чтобы обработчик вызывался, даже если Promise.state!=pending.

function Promise(){
	var state='pending',
		done=[],
		fail=[],
		always=[],
		context,
		_arguments=[],
		execute=function(list){
			var containers=[list,always],
				args=[];

			for(var container in containers){
				if(!containers.hasOwnProperty(container))
					continue;

				container=containers[container];
				for(var i in container){
					if(!container.hasOwnProperty(i))
						continue;

					container[i].apply(context||window,_arguments);
					delete container[i];
				}
			}
		};

	this.set_arguments=function(_args){
		_arguments=[];
		for(var i=0;i<_args.length;i++)
			_arguments.push(_args[i]);

		return this;
	};

	this.resolve=function(){
		state='resolved';
		this.set_arguments(arguments);
		execute(done);

		return this;
	};
	this.reject=function(){
		state='rejected';
		this.set_arguments(arguments);
		execute(fail);

		return this;
	};
	this.done=function(){
		done.push(arguments[0]);
		if(state=='resolved')
			this.resolve.apply(this,_arguments);

		return this;
	};
	this.fail=function(){
		fail.push(arguments[0]);
		if(state=='rejected')
			this.reject.apply(this,_arguments);

		return this;
	};
	this.always=function(){
		always.push(arguments[0]);
		if(state!='pending')
			this[state=='resolved'?'resolve':'reject']();

		return this;
	};
	this.set_context=function(cont){
		context=cont;

		return this;
	};

	function Instance(self){
		var __context=self;

		this.done=function(callback){
			__context.done.call(__context,callback);

			return this;
		};
		this.fail=function(callback){
			__context.fail.call(__context,callback);

			return this;
		};
		this.always=function(callback){
			__context.always.call(__context,callback);

			return this;
		};
		this.set_context=function(context){
			__context.set_context.call(__context,context);

			return this;
		};

		return this;
	};
	this.promise=function(){
		return new Instance(this);
	};

	return this;
}
Ответить с цитированием