• 用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)
    
          })
      }
    }
  • 相关阅读:
    [HEOI2013]Eden 的新背包问题
    [UOJ#77]A+B Problem
    [CodeForces]786B Legacy
    [LUOGU]P4098[HEOI2013]ALO
    [BZOJ3207]花神的嘲讽计划
    [LUOGU]P2633 Count on a tree
    【东莞市选2007】拦截导弹
    [JZOJ] 3462. 【NOIP2013模拟联考5】休息(rest)
    [BZOJ] 2705: [SDOI2012]Longge的问题
    [BZOJ] 1191: [HNOI2006]超级英雄Hero
  • 原文地址:https://www.cnblogs.com/yalong/p/11251490.html
Copyright © 2020-2023  润新知