Promise解析

思想: 在执行本Promise的方法(每个方法都对应着下一个Promise)的时候,将下一个Promise的方法(全部方法)加入到任务队列,其中,最后的Promise的方法为空。

两个数组:成功时要执行的方法数组_doneCallbacks,失败时要执行的方法数组_failCallbacks。

注:根据本Promise方法的执行情况,决定下一个Promise执行哪个数组中的方法(_doneCallbacks还是_failCallbacks)。

			delete window.Promise;

			var Status = {
				PENDING: "pending",
				FULLFILLED: "resolved",
				REJECTED: 'rejected'
			};

			function Promise(func) {
				if(!(this instanceof Promise)) {
					throw new TypeError("TypeError: undefined is not a promise");
				}
				if(typeof func != "function") {
					throw new TypeError("TypeError: Promise's argument is not a function");
				}

				this._status = "pending";
				this._value;
				this._doneCallbacks = [];
				this._failCallbacks = [];

				var promise = this;
				try {
					func(function(data) {
						resolve(promise, data);
					}, function(reason) {
						reject(promise, reason);
					});
				} catch(e) {
					reject(promise, e);
				}

			}

			function resolve(promise, data) {
				if(promise._status !== Status.PENDING) {
					return;
				}

				promise._status = Status.FULLFILLED;
				promise._value = data;

				run(promise);

			}

			function reject(promise, reason) {
				if(promise._status !== Status.PENDING) {
					return;
				}
				promise._status = Status.REJECTED;
				promise._value = reason;

				run(promise);
			}

			function run(promise) {
				if(promise._status === Status.PENDING) {
					return;
				}
				var value = promise._value;
				var callbacks = promise._status === Status.FULLFILLED ? promise._doneCallbacks : promise._failCallbacks;

				//保证
				setTimeout(function() {
					for(var i = 0; i < callbacks.length; i++) {
						callbacks[i](value);
					}
				}, 0);

				promise._doneCallbacks = [];
				promise._failCallbacks = [];
			}

			function empty() {}

			Promise.prototype.then = function(onResolve, onReject) {
				var promise = new Promise(empty);
				this._doneCallbacks.push(makeCallback(promise, onResolve, "resolve"));
				this._failCallbacks.push(makeCallback(promise, onReject, "reject"));
				run(this);
				return promise;
			}

			Promise.prototype.catch = function(onReject) {
				return this.then(null, onReject);
			}

			function makeCallback(promise, callback, action) {
				return function(value) {
					if(typeof callback === "function") {
						var x;
						try {
							x = callback(value);
						} catch(e) {
							reject(promise, e);
							return;
						}
						if(x === promise) {
							var reason = new TypeError("TypeError: The return value could not be same with the promise");
							reject(promise, reason);
						} else if(x instanceof Promise) {
							x.then(function(data) {
								resolve(promise, data);
							}, function(reason) {
								reject(promise, reason);
							});
						} else if(typeof x === "object" || typeof x === "function") {
							//							var then;
							//							try{
							//								then=x.then;
							//							}catch (e){
							//								reject(promise,e);
							//								return;
							//							}
							//							if(typeof then==="function"){
							//								then.call(x,)	
							//							}
						} else {
							resolve(promise, x);
						}
					} else {
						action === "resolve" ? resolve(promise, value) : reject(promise, value);
					}
				}
			}

			Promise.all = function(iterable) {
				if(!iterable || !iterable.hasOwnProperty("length")) {
					throw new TypeError('TypeError: Parameter "iterable" must be a iterable object');
				}

				var promise = new Promise(empty);

				for(var i = 0; i < iterable.length; i++) {
					item = iterable[i];
					if(!(item instanceof Promise)) {
						//转化
					}
					item.then(makeCallBack("resolve"), makeCallBack("reject"));
				}

				var args = [];
				var count = 0;

				function makeCallBack(action) {
					return function(val) {
						if(action === "reject") {
							reject(promise, val);
							return;
						}
						args.push(val);
						if(++count === iterable.length) {
							resolve(promise, args);
						}
					};
				}
				return promise;
			}

			Promise.race = function(iterable) {
				if(!iterable || !iterable.hasOwnProperty("length")) {
					throw new TypeError('TypeError: Parameter "iterable" must be a iterable object');
				}

				var promise = new Promise(empty);

				for(var i = 0; i < iterable.length; i++) {
					item = iterable[i];
					if(!(item instanceof Promise)) {

					}
					item.then(function(data) {
						resolve(promise, data);
					}, function(reason) {
						reject(promise, reason);
					});
				}

				return promise;
			}

			Promise.resolve = function(obj) {
				if(typeof obj !== "object" || typeof obj.then !== "function") {
					return new Promise(function(resolve, reject) {
						resolve(obj);
					});
				}
				if(obj instanceof Promise) {
					return obj;
				}
				if(typeof obj.then === "function") {
					return new Promise(obj.then);
				}
			}

 

阿里前端关于Promise的一道在线编程题:

			//实现 mergePromise 函数,把传进去的数组顺序先后执行,并且把返回的数据先后放到数组(data)中。
			
			//思路:先生成一个fulfilled状态的Promise(假设为W),然后将W后跟的一连串then(f)中的f函数
			//返回值设置为Promise即可
			
			//在(A)promise.then(f)中遇到f的返回值为Promise对象(B),
			//则A从返回值为Promise对象的then处中断then链,转而从头开始执行
			//B所在的then链,当B的then链执行结束(准确说不是结束,后面还有一个空的),
			//重新从断点处唤醒A的then链
			const timeout = ms => new Promise((resolve, reject) => {
				setTimeout(() => {
					resolve();
				}, ms);
			});

			const ajax1 = () => timeout(2000).then(() => {
				console.log('1');
				return 1;
			});

			const ajax2 = () => timeout(1000).then(() => {
				console.log('2');
				return 2;
			});

			const ajax3 = () => timeout(2000).then(() => {
				console.log('3');
				return 3;
			});

			const mergePromise = ajaxArray => {

				return new Promise(function(resolve) {
					let arr = [];
					let cur = Promise.resolve().then(() => {
						return ajaxArray[0]();
					});
					for(let i = 1; i < ajaxArray.length; i++) {
						cur = cur.then((data) => {
							arr.push(data);
							return ajaxArray[i]();
						});
					}
					cur.then((data) => {
						arr.push(data);
						resolve(arr);
					});

//					ajaxArray[0]().then(function(data) {
//						arr.push(data);
//						ajaxArray[1]().then(function(data) {
//							arr.push(data);
//							ajaxArray[2]().then(function(data) {
//								arr.push(data);
//								resolve(arr)
//							});
//						});
//					});
				});
			};

			mergePromise([ajax1, ajax2, ajax3]).then(data => {
				console.log('done');
				console.log(data); // data 为 [1, 2, 3]
			});

			// 分别输出
			// 1
			// 2
			// 3
			// done
			// [1, 2, 3]

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值