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) }) } }