// 手写一个Promise function MyPromise(fun){ // 构造函数接收一个函数 this.status = MyPromise.PENDING // 设置默认状态为待定 try { fun.call(this, MyPromise.resolve.bind(this), MyPromise.reject.bind(this)) } catch(err){ // 如果MyPromise.prototype.then里面有err=>{}处理函数就传递给它 this.status = MyPromise.REJECT this.result = err } } // Promise 状态常量 MyPromise.PENDING = 0 MyPromise.FULFILLED = 1 MyPromise.REJECT = 2 MyPromise.resolve = function(res) { if(this === MyPromise) return new MyPromise(resolve=>resolve(res)) // 如果是静态调用就返回一个确认的Promise if(this.status === MyPromise.REJECT) return // Promise 的状态一旦确定就不能修改 this.status = MyPromise.FULFILLED this.result = res } MyPromise.reject = function(err) { if(this === MyPromise) return new MyPromise((resolve,reject)=>reject(err)) // 如果是静态调用就返回一个拒绝的Promise if(this.status === MyPromise.FULFILLED) return // Promise 的状态一旦确定就不能修改 this.status = MyPromise.REJECT this.result = err } MyPromise.prototype = { then: function(res, err){ // Promise的.then要加入到任务队列,不能同步执行用setTimeout模拟 var context = this // 保存的上下文 setTimeout(function(){ // 在.then中无论是onFulfilled的返回值还是onReject的返回值,都会交给下一个.then的onFulfilled处理,只有出现异常的时候才后交给下一个.then的onReject处理 try{ if(context.status === MyPromise.FULFILLED && res) context.result = res(context.result) if(context.status === MyPromise.REJECT && err) { context.result =err(context.result) context.status = MyPromise.FULFILLED } }catch(err){ context.result = err context.status = MyPromise.REJECT } }, 0); return this } } // 编写Promise.all([...Promies])静态方法 /** * @description 接受一个Promise的迭代对象,当全部的Promise兑现时,返回一个由兑现值组成的迭代对象 * 当为空的迭代对象时也会对象一个空的迭代对象 Promise.all([]).then(res=>{console.log(res)}) res = [] */ MyPromise.all = function (ps) { if(typeof ps[Symbol.iterator] !== 'function') throw new Error("传递一个内容为Promise实例的可迭代对象") var n = ps.length var rs = [] for(var i = 0; i < n; i++) { (function(i){ ps[i].then(res=>{ rs[i] = res }, err=>{ // all只要出现拒绝,就立马返回第一个拒绝的内容 this.status = MyPromise.REJECT; this.result = err }) }).call(this, i) } if (this.status === MyPromise.REJECT) return this this.status = MyPromise.FULFILLED this.result = rs return this }