Promise A+
概念
不仅是一种异步解决的方案,也是一种规范。
了解promise流程,并自己实现一个promise
文档地址:
解读
术语:
then()必须遵守规范thenable是一个对象或函数并定义一个方法value值是JavaScript的值包括undefined/thenable/promiseexception另外 是一个抛出的异常reason一个指示为什么造成失败或拒绝的值
要求:
Promise有三个状态(等待pending, 被满足fulfilled, 拒绝reject)pending等待态 可变成功状态或失败状态fulfilled成功态 不能转换为其他状态,必须有值且不能更改reject失败态 不能转换为其他状态,必须有值且不能更改
必须提供一个
then()方法去访问它当前值/最终值/原因,then()方法接收两个参数(均为函数):onFulfilled: 必须作为函数被调用(不可用this代替),不是函数时会被忽略掉,必须为异步不阻塞程序向下执行onRejected: 必须作为函数被调用(不可用this代替),不是函数时会被忽略掉 ,必须为异步不阻塞程序向下执行- 以上两个参数都是可选填写
- 如果参数是函数时,在fulfilled状态时才能执行且只能执行一次
- 传值:
resolve(123)该传值是promise.then(res => console.log(res))里then()的第一个参数里函数里的形参
then()可以被多次调用,链式调用,调用时里面的函数参数是依次顺序调用- 当
promise是成功态的时候,所有各自的onFulfilled的回调函数必须按原有的调用顺序来执行 - 当
promise是失败态的时候,所有各自的onRejected的回调函数必须按原有的调用顺序来执行
- 当
then()必须返回一个promise, 即let promise2 = promise1.then(...)onFulfilled/onRejected函数执行完毕返回一个x, 即let x = onFulfilled(value);x有可能是普通值(需要resolve()抛出), 也有可能是一个promise- 无论是成功还是失败的回调遇到抛出异常时,
promise2里必须执行reject()并返回原因
resolvePromise函数:- 如果
promise和x指向同一个引用,必须返回一个带有reject原因的promise,并报错TypeError: Chaining cycle detected for pormise死循环 - 当
x是一个对象或函数时:将then赋值为x.then,执行then改变指向为x即实例化对象,且带有两个回调函数 - 当
x是不是一个对象或函数时:返回普通值 resolve/reject只能2选1执行
- 如果
关于执行器:
/*** Promise(){}* 参数:@excutor 执行器 自动执行的回调函数*/let promise = new Promise(//excutor (resolve, reject) => { });
实现
功能一
resolve/reject/exception/指定状态/抛出异常
//index.js//使用const MyPromise = require('./MyPromise');let promise = new MyPromise((resolve, reject) => {// resolve('success');// reject('error');//另外抛出的错误 exception// throw new Error('Exception: Error');});promise.then(//onFulfilled(value) => {console.log('Fulfilled: ' + value);},//onRejected(reason) => {console.log('Rejected: ' + reason);});
//MyPromise.js//定义三种状态const PENDING = 'PENDING',FULFILLED = 'FULFILLED',REJECTED = 'REJECTED';class MyPromise {//excutor执行器 自动执行的回调函数constructor(executor) {//初始化状态this.status = PENDING;//初始化value/reason//resolve()执行前是undefinedthis.value = undefined;this.reason = undefined;//excutor都有自己的resolve和reject函数const resolve = (value) => {//pending可变成功状态if (this.status === PENDING) {this.status = FULFILLED;this.value = value;}};const reject = (reason) => {//pending可变失败状态if (this.status === PENDING) {this.status = REJECTED;this.reason = reason;}};//捕获 new Promise时抛出的异常try {executor(resolve, reject);} catch (e) {//当捕获到时走reject函数reject(e);}//当实例化MyPromise时立即执行//executor()里的两个参数均为函数executor(resolve, reject);}//定义then()方法 可多次调用执行//onFulfilled 成功时的回调//onRejected 失败时的回调then(onFulfilled, onRejected) {// console.log(this.status);if (this.status === FULFILLED) {onFulfilled(this.value);}if (this.status === REJECTED) {onRejected(this.reason);}}}module.exports = MyPromise;
问题1:为什么抛出异常时程序不会走onRejected函数?
当executor函数执行后抛出的异常
问题2:如何实现抛出异常时程序会走onRejected函数?
可以在MyPromise内部定义try..catch来捕获异常
//捕获 new Promise时抛出的异常try {executor(resolve, reject);} catch (e) {//当捕获到时走reject函数reject(e);}
功能二
依次执行promise.then()写法/链式调用
原生Promise链式调用的特点:
- 通过
return来传递结果 - 通过新的
promise resolve结果 - 通过新的
promise reject原因 then()走了失败的回调函数后,再走then()then()中使用throw new Error()- 可以用
catch捕获异常
总结:
catch在Promise的源 码层面上就是一个then,catch也是遵循then的运行原则成功的条件:
then return一个普通的JavaScript值then return新的promise成功态的结果
失败的条件:
then return新的promise失败态的原因then throw抛出了异常
promise链式调用的原理是返回了一个新的Promise类 (then不具备this)
//1.通过return来传递结果promise.then((res) => { return res; }).then((res) => { console.log(res); })//2.通过新的promise resolve结果promise.then((res) => { return res; }).then((res) => { return new Promise((resolve, reject) => { resolve(res); }) }).then((res) => { console.log(res); })//3.通过新的promise reject原因promise.then((res) => { return res; }).then((res) => { return new Promise((resolve, reject) => { reject('ERROR'); }) }).then((res) => { console.log(res); },(err) => { console.log('Reject:' + err); },)//4.then()走了失败的回调函数后,再走then()的结果是什么?//没有return 值默认为undefinedpromise.then((res) => { return res; }).then((res) => { return new Promise((resolve, reject) => { reject('ERROR'); }) }).then((res) => { //默认return undefined; console.log(res); },(err) => { console.log('Reject:' + err); },).then((value) => { console.log('Fulfilled: ' + value); }, //打印Fulfilled: undefined(reason) => { console.log('Reject:' + reason); },);//5.then()中使用throw new Error()会是怎么样的结果?//出现抛出异常的结果promise.then((res) => { return res; }).then((res) => { return new Promise((resolve, reject) => { reject('ERROR'); }) }).then((res) => { console.log(res); },(err) => { console.log('Reject:' + err); },).then((value) => { throw new Error('Throw Error'); }).then((value) => { console.log(value) }, (reason) => { console.log('Exeption: ' + reason) });//6.可以用catch捕获异常//没有写失败的回调时候程序走catch Error//有写失败的回调时候程序走失败的回调promise.then((res) => { return res; }).then((res) => { return new Promise((resolve, reject) => { reject('ERROR'); }) }).then((res) => { console.log(res); },(err) => { console.log('Reject:' + err); },).then((value) => { throw new Error('Throw Error'); }).then((value) => { console.log(value) }).catch((err) => { console.log('Catch: ' + err)});
如果then()里含有异步函数会等待执行
//如何实现如果then()里含有异步函数会等待执行?promise.then((res) => { return res; }).then((res) => {return new Promise((resolve, reject) => {setTimeout(() => {resolve(res);}, 2000);});}).then((res) => { console.log(res); })//为什么遇到异步程序时不打印结果的原因://exector执行完毕 -> 状态没有改变(PENDING) -> 导致then(()=>{},()=>{})无法判断走哪个程序 -> 不打印任何数据//实现原理:如果程序走到then()里是PENDING状态时 -> 发布订阅模式 -> 订阅者收集所有的onFulfilled/onRejected的回调函数 -> 定义自己的resolve函数时发布 -> 当resolve()执行 -> 执行容器内所有的onFulfilled/onRejected方法 -> 实现异步等待时间加载class MyPromise {//excutor执行器 自动执行的回调函数constructor(executor) {...//初始化收集所有的onFulfilled/onRejected的回调函数的容器this.onFulfilledCallbacks = [];this.onRejectedCallbacks = [];const resolve = (value) => {//pending可变成功状态if (this.status === PENDING) {this.status = FULFILLED;this.value = value;//发布模式:this.onFulfilledCallbacks.forEach((fn) => {fn();})}};const reject = (reason) => {//pending可变失败状态if (this.status === PENDING) {this.status = REJECTED;this.reason = reason;//发布模式:this.onRejectedCallbacks.forEach((fn) => {fn();})}};...}//onFulfilled 成功时的回调//onRejected 失败时的回调then(onFulfilled, onRejected) {...//订阅过程if (this.status === PENDING) {//订阅模式:收集所有的onFulfilled/onRejected的回调函数到容器里//数组里存放的是 仍未执行调用的函数体()=>{...}this.onFulfilledCallbacks.push(() => {//因为需要传参this.value 所以用函数嵌套的方式写onFulfilled(this.value);});this.onRejectedCallbacks.push(() => {onRejected(this.reason);});}}}
//实现功能二:链式调用的实现function resolvePromise(promise2, x, resolve, reject) {console.log(promise2, x);}class MyPromise {constructor(executor) {...};}//定义then()方法 可多次调用执行then(onFulfilled, onRejected) {//实现:then()返回一个新的Promise//onFulfilled/onRejected函数执行完毕返回一个x `let x = onFulfilled(value);`//x有可能是普通值(需要抛出), 也有可能是一个promiselet promise2 = new MyPromise((resolve, reject) => {if (this.status === FULFILLED) {//必须为异步程序且不阻塞程序向下执行setTimeout(() => {//无论是成功还是失败的回调遇到抛出异常时,promise2里必须执行`reject()`并返回原因try {//如有new Error()异常,捕获它//普通值x需要处理且不能直接resolve()抛出,因为会影响程序后面返回new Promise()的执行let x = onFulfilled(this.value);/*** 专门处理x的函数* resolvePromise()* 参数1:@promise2 被抛出的promise2的成功/失败是未知的* 参数2:@x onFulfilled() 返回的值有可能是普通值/promise* 参数3: @resolve 因为外部无法访问内部的resolve所以需传入* 参数4: @reject 因为外部无法访问内部的reject所以需传入*/resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);}if (this.status === REJECTED) {setTimeout(() => {try {let x = onRejected(this.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);}if (this.status === PENDING) {this.onFulfilledCallbacks.push(() => {try {let x = onFulfilled(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}});this.onRejectedCallbacks.push(() => {try {let x = onRejected(this.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}});}});return promise2;}}module.exports = MyPromise;
功能三
报错/处理x值/返回普通值或promise
//原生Promise分析let promise1 = new Promise((resolve, reject) => {resolve('promise1');});let promise2 = promise1.then(() => {return 1;}, (reason) => {return reason;});promise2.then((value) => {console.log(value);}, (reason) => {console.log(reason);});
//实现报错:function resolvePromise(promise2, x, resolve, reject) {//如果promise和x指向同一个引用,必须返回一个带有reject原因的promise//并报错`TypeError: Chaining cycle detected for pormise`死循环if (x === promise2) {return reject(new TypeError('Chaining cycle detected for pormise'));}}
//返回普通值或promisefunction resolvePromise(promise2, x, resolve, reject) {//如果promise和x指向同一个引用,必须返回一个带有reject原因的promise//并报错`TypeError: Chaining cycle detected for pormise`死循环if (x === promise2) {return reject(new TypeError('Chaining cycle detected for pormise'));}//resolve/reject 只能2选1执行let called = false;//当x是对象或函数时if (typeof x === 'object' && x !== null || typeof x === 'function') {//仍需捕获try {let then = x.then;//如果then是一个函数证明x里有一个then方法//说明这里面也是一个Promiseif (typeof then === 'function') {//是promise//指向x promise实例对象//文档命名:y 成功函数//文档命名:r 失败函数then.call(x, (y) => {//如果调用过了,中止if (called) return;called = true;resolvePromise(promise2, y, resolve, reject);}, (r) => {if (called) return;called = true;//多层嵌套时需要递归reject(r);});} else {//不是promise时返回一个普通值resolve(x);}} catch (e) {if (called) return;called = true;reject(e);}} else {//不是对象或函数时返回一个普通值resolve(x);}}
//实现then().then().then()... 链式调用时没有参数可以穿透执行得到结果then(onFulfilled, onRejected) {//实现穿透 给默认值//是函数是用该函数,不是函数时给一个新的函数,值是value / reason直接抛出onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason};...}
//实现 catch()语法时也能拿到错误原因catch (errorCallback) {//跟then几乎一样,但第一个参数是null不用填//说明catch只是then的一个语法糖return this.then(null, errorCallback);}
实现resolve和reject的静态方法
Promise.resolve();Promise.reject();
//实现class MyPromise {...static resolve(value) {return new MyPromise((resolve, reject) => {resolve(value);});}static reject(error) {return new MyPromise((resolve, reject) => {reject(error);});}}
静态方法
Promise.all()
是一个静态方法
情景:通过readFile API 读取多个文件 会存在嵌套的问题,且代码不内聚
readFile('./data1.json').then((res) => {dataArr.push(res);readFile('./data2.json').then((res) => {dataArr.push(res);...});});
Promise.all()方法可以解决上述问题
//写法Promise.all([1,readFile('./data1.json'),readFile('./data2.json'),]).then((res) => {console.log(res);});
原理:
遇到普通值 -> 直接处理 / 遇到promise-> 走promise程序 -> resolve/reject
弊端:
单一遇到错误,不会返回结果,只有数组中的每一个promise必须全部成功才能返回结果
重写Promise.all()静态方法
class MyPromise {...static all(promiseArr) {let resArr = [],idx = 0;return new MyPromise((resolve, reject) => {promiseArr.map((promise, index) => {if (isPromise(promise)) {promise.then((res) => {formatResArr(res, index, resolve);}, reject);} else {formatResArr(res, index, resolve);}});});function formatResArr(value, index, resolve) {resArr[index] = value;//这里idx自增 是为了防止有异步promise返回时间不确定,也有可能出现并发的情况if (++idx === promiseArr.length) {resolve(resArr);}}function isPromise(x) {if ((typeof x === 'object' && x !== null) || typeof x === 'function') {let then = x.then;return typeof then === 'function';}return false;}}}
Promise.allSettled()
类似Promise.all()方法,返回的是多个promise集合的数组结果,但区别于的是,它可以返回错误和成功的结果
Promise.allSettled([p1,p2].then((res) => {console.log(res);}))//打印[{ status: 'fulfilled', value: 'success' },{ status: 'rejected', value: 'error' }]
重写Promise.allSettled()静态方法
class MyPromise {...static allSettled(promiseArr) {let resArr = [],idx = 0;//判断promiseArr是否是可迭代对象if (!isIterable(promiseArr)) {throw new TypeError('MyError: ' + promiseArr + ' is not iterable (cannot read property Symbol(Symbol.iterator))');}return new Promise((resolve, reject) => {//如果第一个参数为空的情况if (promiseArr.length === 0) {resolve([]);}promiseArr.map((promise, index) => {if (isPromise(promise)) {promise.then((value) => {formatResArr('fulfilled', value, index, resolve);}, (reason) => {formatResArr('rejected', reason, index, resolve);})} else {formatResArr('fulfilled', promise, index, resolve);}});});function formatResArr(status, value, index, resolve) {//status -> 成功/失败switch (status) {case 'fulfilled':resArr[index] = {status,value}break;case 'rejected':resArr[index] = {status,reason: value}break;default:break;}if (++idx === promiseArr.length) {resolve(resArr);}}function isIterable(value) {return value !== null && value !== undefined && typeof value[Symbol.iterator] === 'function';}}}
Promise.race()
谁先有结果,得到先到的结果
let p1 = new Promise((resolve, reject) => {resolve('success');});let p2 = new Promise((resolve, reject) => {reject('error');});//Promise.race(可迭代的对象或数组)Promise.race([p1, p2, 'other']).then((res) => {console.log(res);});
实现
My Promise{...static race(promiseArr){return new MyPromise((resolev, reject) => {promiseArr.map((promise) => {if(isPromise(promise)){//直接then 拿到resolve/reject结果promise.then(resolve, reject);}else{//普通值直接抛出resolve(promise);}});});}}
Promise.finally()
- 无论外面
Promise成功还是失败 都走 并且回调不带参数 - 正常走
finally之后then或者catch - 如果
finally内部有promise并且有延时处理 整个finally会等待 - 如果两个都成功走外面 取外面结果
- 如果外面是成功 里面是失败 取里面失败结果
- 如果外面是失败 里面是成功 取外面失败结果
- 如果外面是失败 里面是失败 取里面失败结果
- 如果外面是成功 里面是成功 取外面成功结果
Promise.reject('result1').finally(() => {return new Promise(resolve, reject) => {setTimeout(() => {resolve('new Promise error');}, 2000);}});
//实现MyFinallyMy Promise{...MyFinally(finallyCallback){return this.then((value) => {return MyPromise.resolve(finallyCallback()).then(() => value);}, (reason) => {return MyPromise.resolve(finallyCallback()).then(() => {throw reason;});});}}
promisify
node开发环境中会经常使用到promisify, 因为node Api 属于回调式的,希望把代码转为promisify格式作为内置调用的一种形式
//模拟fsconst fs = require('fs');fs.readFile('./data/user.json', 'utf8', (err, data) => {});
//node内置API promises属性const fs = require('fs').promises;fs.readFile('./data/user.json', 'utf8').then((res) => {},(err) => {});
//bluebird库 异步处理方法 promisify()const readFile = bluebird.promisify(fs.readFile);readFile('./data/user.json', 'utf8').then((res) => {},(err) => {});
//node工具库 util util.promisify()const util = require('util');const readFile = util.promisify(fs.readFile);readFile('./data/user.json', 'utf8').then((res) => {},(err) => {});
模拟实现util里面的promisify()方法 实现异步处理
module.exports = {//接收函数方法 如fs.readFilepromisify(fn){//返回一个函数 如readFile(promise).then()//...args形参 => './data/user.json', 'utf8'return function(...args){return new Promise((resolve, reject) => {//fs.readFile//fn()执行后才能then()//参数2:原生带有一个自定义的回调函数fn(...args, (error, data) => {if(error){return reject(error);}resolve(data);});})}}}
promisifyAll
把一个对象里的所有方法全部promisify一遍
module.exports = {promisify(fn){...},promisifyAll(fns){//遍历每一个方法且加上async// Object.keys()遍历出自身的可枚举的键名(不含继承属性)Object.keys(fns).map((fnName) => {//有可能不是方法而是属性,需排除if(typeof fns[fnName] === 'function'){//1.更改名称fns[fnName + 'Async'] = this.promisify(fns[fnName]);}});//返回包装后的fnsreturn fns;}}
源码
PromiseA+案例所有源码:
//定义三种状态const PENDING = 'PENDING',FULFILLED = 'FULFILLED',REJECTED = 'REJECTED';function resolvePromise(promise2, x, resolve, reject) {//如果promise和x指向同一个引用,必须返回一个带有reject原因的promise//并报错`TypeError: Chaining cycle detected for pormise`死循环if (x === promise2) {return reject(new TypeError('Chaining cycle detected for pormise'));}//resolve/reject 只能2选1执行let called = false;//当x是对象或函数时if (typeof x === 'object' && x !== null || typeof x === 'function') {//仍需捕获try {let then = x.then;//如果then是一个函数证明x里有一个then方法//说明这里面也是一个Promiseif (typeof then === 'function') {//是promise//指向x promise实例对象//文档命名:y 成功函数//文档命名:r 失败函数then.call(x, (y) => {//如果调用过了,中止if (called) return;called = true;resolvePromise(promise2, y, resolve, reject);}, (r) => {if (called) return;called = true;//多层嵌套时需要递归reject(r);});} else {//不是promise时返回一个普通值resolve(x);}} catch (e) {if (called) return;called = true;reject(e);}} else {//不是对象或函数时返回一个普通值resolve(x);}}function isPromise(x) {if ((typeof x === 'object' && x !== null) || typeof x === 'function') {let then = x.then;return typeof then === 'function';}return false;}function isIterable(value) {return value !== null && value !== undefined && typeof value[Symbol.iterator] === 'function';}class MyPromise {//excutor执行器 自动执行的回调函数constructor(executor) {//初始化状态this.status = PENDING;//初始化value/reason//resolve()执行前是undefinedthis.value = undefined;this.reason = undefined;//初始化收集所有的onFulfilled/onRejected的回调函数的容器this.onFulfilledCallbacks = [];this.onRejectedCallbacks = [];//excutor都有自己的resolve和reject函数const resolve = (value) => {if (value instanceof MyPromise) {value.then((x) => {resolve(x);}, reject);return;}//pending可变成功状态if (this.status === PENDING) {this.status = FULFILLED;this.value = value;//发布模式:this.onFulfilledCallbacks.forEach((fn) => {fn();})}};const reject = (reason) => {//pending可变失败状态if (this.status === PENDING) {this.status = REJECTED;this.reason = reason;//发布模式:this.onRejectedCallbacks.forEach((fn) => {fn();})}};//捕获 new Promise时抛出的异常try {executor(resolve, reject);} catch (e) {//当捕获到时走reject函数reject(e);}//当实例化MyPromise时立即执行//executor()里的两个参数均为函数executor(resolve, reject);}//定义then()方法 可多次调用执行//onFulfilled 成功时的回调//onRejected 失败时的回调then(onFulfilled, onRejected) {//实现穿透 给默认值//是函数是用该函数,不是函数时给一个新的函数,值是value / reason直接抛出onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason};//实现:then()返回一个新的Promise//onFulfilled/onRejected函数执行完毕返回一个x `let x = onFulfilled(value);`//x有可能是普通值(需要抛出), 也有可能是一个promiselet promise2 = new MyPromise((resolve, reject) => {if (this.status === FULFILLED) {//必须为异步程序且不阻塞程序向下执行setTimeout(() => {//无论是成功还是失败的回调遇到抛出异常时,promise2里必须执行`reject()`并返回原因try {//如有new Error()异常,捕获它//普通值x需要处理且不能直接resolve()抛出,因为会影响程序后面返回new Promise()的执行let x = onFulfilled(this.value);/*** 专门处理x的函数* resolvePromise()* 参数1:@promise2 被抛出的promise2的成功/失败是未知的* 参数2:@x onFulfilled() 返回的值有可能是普通值/promise* 参数3: @resolve 因为外部无法访问内部的resolve所以需传入* 参数4: @reject 因为外部无法访问内部的reject所以需传入*/resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);}if (this.status === REJECTED) {setTimeout(() => {try {let x = onRejected(this.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);}if (this.status === PENDING) {//订阅模式:收集所有的onFulfilled/onRejected的回调函数到容器里//数组里存放的是 仍未执行调用的函数体()=>{...}this.onFulfilledCallbacks.push(() => {setTimeout(() => {try {//因为需要传参this.value 所以用函数嵌套的方式写let x = onFulfilled(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);});this.onRejectedCallbacks.push(() => {setTimeout(() => {try {let x = onRejected(this.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);});}});return promise2;}catch (errorCallback) {//跟then几乎一样,但第一个参数是null不用填//说明catch只是then的一个语法糖return this.then(null, errorCallback);}static resolve(value) {return new MyPromise((resolve, reject) => {resolve(value);});}static reject(error) {return new MyPromise((resolve, reject) => {reject(error);});}static all(promiseArr) {let resArr = [],idx = 0;return new MyPromise((resolve, reject) => {promiseArr.map((promise, index) => {if (isPromise(promise)) {promise.then((res) => {formatResArr(res, index, resolve);}, reject);} else {formatResArr(res, index, resolve);}});});function formatResArr(value, index, resolve) {resArr[index] = value;if (++idx === promiseArr.length) {resolve(resArr);}}}static allSettled(promiseArr) {let resArr = [],idx = 0;//判断promiseArr是否是可迭代对象if (!isIterable(promiseArr)) {throw new TypeError('MyError: ' + promiseArr + ' is not iterable (cannot read property Symbol(Symbol.iterator))');}return new Promise((resolve, reject) => {//如果第一个参数为空的情况if (promiseArr.length === 0) {resolve([]);}promiseArr.map((promise, index) => {if (isPromise(promise)) {promise.then((value) => {formatResArr('fulfilled', value, index, resolve);}, (reason) => {formatResArr('rejected', reason, index, resolve);})} else {formatResArr('fulfilled', promise, index, resolve);}});});function formatResArr(status, value, index, resolve) {//status -> 成功/失败switch (status) {case 'fulfilled':resArr[index] = {status,value}break;case 'rejected':resArr[index] = {status,reason: value}break;default:break;}if (++idx === promiseArr.length) {resolve(resArr);}}}}module.exports = MyPromise;
