用es6实现一个promsie

Promise 使用方法: https://www.runoob.com/w3cnote/javascript-promise-object.html

直接上代码,相关的解释都在代码的注释里面,这里以minPromise 代替 Promise:

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>

<script type="text/javascript">
	class minPromise {
		/** 
		比如 
		var p = new minPromise ((resolve, reject)=> {
			 // 这里是处理的代码,脑补
		})
		那么 executor 就是 (resolve, reject) => { ... }
		**/
		constructor(executor){
			// executor 必须是 function 类型
			if (typeof executor !== 'function') {
		      throw new Error('Executor must be a function');
		    }
		    
		    // 初始状态是 PENDING
		 	this.state = 'PENDING';
		    this.chained = [];

			const resolve = res => {
				// 如果状态不是 PENDING 那就不进行处理了
		    	if (this.state !== 'PENDING') {
		        	return;
		      	}

		      	// 假如说res这个对象有then的方法,我们就认为res是一个promise
		      	if (res != null && typeof res.then === 'function') {
		        	return res.then(resolve, reject);
		      	}

		      	this.state = 'FULFILLED';
		      	this.internalValue = res;
		      	// 这里用到 解构 相当于 for(let item of this.chainer) 然后 { onFulfilled }  = item , 下同
		      	for (let { onFulfilled } of this.chained) {
		        	onFulfilled(res);
		      	}
		    };

	     	const reject = err => {
		      	if (this.state !== 'PENDING') {
	       	 		return;
		      	}
		      	this.state = 'REJECTED';
		      	this.internalValue = err;
		      	for (const { onRejected } of this.chained) {
		        	onRejected(err);
		      	}
		    };

		    // 这里相当于函数初始运行 利用了构造函数自动执行的特性
		    try{
				executor(resolve, reject);
		    }catch(err){
		    	reject(err);
		    }
		}

		// 状态是 FULFILLED 或者 REJECTED 说明已经执行完 resolve 方法, internalValue 也已经有值了,可以直接执行
		// 状态是 PENDING 说明 resolve 的方法是异步的, 就先把  onFulfilled, onRejected 事件放到 chained 里面,存起来,等 resolve 的时候在执行
	   

	   // 如果不需要then的链式调用, 用这个then就可以
	   //  then(onFulfilled, onRejected) {
		  //   if (this.state === 'FULFILLED') {
		  //     	onFulfilled(this.internalValue);
		  //   } else if (this.state === 'REJECTED') {
		  //     onRejected(this.internalValue);
		  //   } else {
		  //     	this.chained.push({ onFulfilled, onRejected });
		  //   }
	  	// }

	  	// 需要then的链式调用的话 让then返回 Promise 就行
	  	then(onFulfilled, onRejected) {
		    return new minPromise((resolve, reject) => {
		      // 这里把	onFulfilled  onRejected 封装了下 是因为 resolve(onFulfilled(res))  或者 reject(onRejected(err)) 执行的时候 有可能报错,做了错误兼容处理
		      const _onFulfilled = res => {
		        try {
		          //注意这里resolve有可能要处理的是一个promise
		          resolve(onFulfilled(res));
		        } catch (err) {
		          reject(err);
		        }
		      };
		      const _onRejected = err => {
		        try {
		          reject(onRejected(err));
		        } catch (_err) {
		          reject(_err);
		        }
		      };
		      if (this.state === 'FULFILLED') {
		        _onFulfilled(this.internalValue);
		      } else if (this.state === 'REJECTED') {
		        _onRejected(this.internalValue);
		      } else {
		        this.chained.push({ onFulfilled: _onFulfilled, onRejected: _onRejected });
		      }
		    });
	    },
	    // resolve方法 相当于返回一个Promise对象
	    resolve(value) {
	    	return new minPromise(value => {
	    		resolve(value);
	    	})
	    },
	    reject(reason) {
	        return new minPromise((resolve, reject) => {
	            reject(reason);
	        });
	    },
	    // 全部成功的时候返回的是一个结果数组,失败的时候 会直返回失败
		all(promiseArr) {
		    return new minPromise((res, rej)  => {
		        // promiseArr 所有的值都看一下
		        var arr = [];
		        var times = 0;
		        processResult =  (index, result) =>{
		            arr[index] = result;
		            times++;
		            // arr.length == promiseArr.length, 代表全部都 resolve 成功
		            if (times ==  promiseArr.length) {
		            	// 在这里执行最后的 resolve
		                res(arr);
		            }
		        };

		        for (let i = 0; i < promiseArr.length; i++) {
		            var oPromise = promiseArr[i];
		            // 是 promise
		            if (typeof oPromise.then == 'function') {
		                oPromise.then((val) =>{
		                	// then 成功后把值存下来
		                    processResult(i, val)
		                }, (reason) =>{
		                    // 不成功 直接 reject
		                    rej(reason);
		                })
		            }else {
		                processResult(i, oPromise);
		            }
		        }
		    });
		},

	    // 哪个实例获得结果最快,就返回那个结果,不管结果本身是成功还是失败;
	    race(promiseArr) {
		    return new minPromise((resolve, reject) => {
		        promiseArr.forEach((promise) => {
		           promise.then(resolve, reject);
		        });
		    });
		},

	}

	// 测试非链式调用
	let p = new minPromise(resolve => {
  		setTimeout(() => resolve('Hello'), 100);
	});

	p.then(res => console.log(res));

	p = new minPromise((resolve, reject) => {
	  setTimeout(() => reject(new Error('woops')), 100);
	});

	p.then(() => {}, err => console.log('Async error:', err.stack));


	// 测试链式调用
	let p2 = new minPromise(resolve => {
	  setTimeout(() => resolve('World'), 100);
	});

	p2.
  	then(res => new minPromise(resolve => resolve(`Hello, ${res}`))).
 	then(res => console.log(res));

</script>

</body>
</html>

  参考: https://segmentfault.com/a/1190000014440641   , https://juejin.im/post/5aa7868b6fb9a028dd4de672#heading-9

2020.3.11 新增:

all(promiseArr) {
  let result = []
  promiseArr.forEach((item, index) => {

      item.then(res => {

        result[index] = res

        i++

        if(i === promiseArr.length) {

          resolve(result)

        }

      }, err => {

        reject(err)

      })
  }
}

参考资料:

promise.all的手动实现:https://zhuanlan.zhihu.com/p/41502945 

 

posted @ 2019-07-26 17:01  进军的蜗牛  阅读(427)  评论(0编辑  收藏  举报