使用ES6中Class实现手写PromiseA+,完美通过官方872条用例

来源 | https://www.cnblogs.com/echoyya/p/14695457.html
Promise出现的原因
Promise 是异步编程的一种解决方案,比传统的解决方案回调函数和事件更合理和更强大,Promise的出现主要解决以下两个问题:
回调地狱: 某个异步操作需要等待之前的操作完成在继续执行, 当这样的需求多了以后, 使的代码进入无尽的嵌套,可读性降低不好维护。 异步和同步之间的联系问题:当一个同步操作需要等待多个异步操作的结果, 这样会使得代码的逻辑变得相对来说比较复杂。
myPromise的实现要点
Promise 就是一个类,实际上就是ES6提供的一个新的构造函数, 通过new创建实例,接收一个函数作为参数,并且该函数中的代码默认是同步代码,会立即执行 Promise 有三种状态,成功resolved,失败rejected,等待pedding Promise 状态一旦发生改变,就不能在改变,状态不可逆 用户可自定义成功的数据及失败的原因 Promise 实例拥有一个then方法。接受两个参数,一个成功回调,一个失败回调 executor执行器在执行过程中,可能会抛出异常 throw new Error(),需要 try catch 捕获 当执行器中的是异步代码时(如定时器执行resolve),不是立即执行 状态不会变更,此时then方法中状态仍然是pending 一个 promise 实例可以被 then 多次,分别创建一个队列用来存放成功和失败回调事件 定时器执行时,判断状态为 pending,非立即执行,而是先存放 成功/失败 回调事件 等待状态变为成功或失败时遍历队列依次执行对应的onfulfilled和onrejected,并且有执行顺序 Promise 实现链式调用,返回的并不是this,而是一个新的promise实例, 因为原有的promise状态一旦发生改变,就不能再改变,否则不符合规范 Promise 成功和失败的回调的返回值,可以传递给下一次的的then
返回的是普通值:不论then是成功还是失败。只要是普通值就传递到下一次then的成功中。(普通值包括:非错误非promise,包括对象) 报错或异常:一定会走到下一次then的失败中。如果离自己最近的then没有错误处理,会向下找 特别注意: return new Error()返回的是错误对象,属于普通值走下一次then的成功,而throw new Error() 是抛出异常,需要try catch 会走下一次的失败 返回的是promise:会采用promise的状态,决定下一次then是成功还是失败,此处会有递归判断 总结: 如果返回一个普通值,除了promise ,就传递给下一个then的成功,如果返回一个失败的promise或者抛出异常,会走下一个then的失败。
Promise 值的穿透,当一个promise连续then 多次,并且then中没有返回任何值时,此时data会穿透至最后一个then中 14.1 执行onfulfilled时,先判断是不是一个function,如果是就直接执行,反之就包一层函数 14.2 执行onrejected时,先判断是不是一个function,如果是就直接执行,反之就抛出失败异常 既然promise是为了解决异步回调函数嵌套问题,那么可以通过promise的延迟对象来减少一层嵌套关系 promiseA+ 规范测试 聊点规范以外的东东吧~~catch, finally,resolve,reject,all,race,就这么多
myPromise的实现
下面就来实现以上要点
myPromise — 实现简单的同步
myPromise.js
// 要点 3: 有三种状态, 相当于是常量,可以放在外面const RESOLVED = 'RESOLVED'const REJECTED = 'REJECTED'const PENDING = 'PENDING'// 要点 1: Promise 就是一个类class Promise {// 要点 2: 接收一个函数executor作为参数,立即执行constructor(executor) {this.status = PENDINGthis.value = undefined // 要点 5: 用户可自定义 成功的数据this.reason = undefined // 要点 5: 用户可自定义 失败的原因let resolve = (value) => {// 要点 4: 状态不可逆, 只有PENDING时,才可以改变状态if (this.status === PENDING) {this.value = value // 成功的数据this.status = RESOLVED // 状态置为 RESOLVED}}let reject = (reason) => {// 要点 4: 状态不可逆, 只有PENDING时,才可以改变状态if (this.status === PENDING) {this.reason = reason // 失败的原因this.status = REJECTED // 状态置为 REJECTED}}// 要点 7: 错误处理,抛出异常 throw new Error()try {executor(resolve, reject) // 立即执行} catch(e) { // 抛出异常 直接失败reject(e)}}// 要点 6: 拥有一个then方法(实例上的方法)。接受两个参数回调函数then(onfulfilled, onrejected) {if(this.status === RESOLVED){onfulfilled(this.value)}if(this.status === REJECTED){onrejected(this.reason)}}}// Commonjs规范导出模块module.exports = Promise
test.js 简单的同步操作验证
// 使用自己的promise,注释该行代码,就是原生promiselet Promise = require('./1.myPromise')let p = new Promise((resolve, reject) => {resolve('成功')// throw new Error('失败了')// reject('失败')})p.then((data) => {console.log(data)}, (err) => {console.log(err)})
myPromise — 增加异步功能
在实现了简单的同步操作后,再来看看异步代码的执行,还是使用上面 test 中的案例,简单的改造一下,写一个定时器模拟异步环境,test.js:增加异步功能。
let Promise = require('./1.myPromise')let p = new Promise((resolve, reject) => {setTimeout(()=>{resolve('成功')},1000)})p.then((data) => {console.log(data,1)}, (err) => {console.log(err)})// 一个实例可以then多次,执行结果会是一样的,因为状态已经固定p.then((data) => {console.log(data,2)}, (err) => {console.log(err)})
myPromise.js
const RESOLVED = 'RESOLVED'const REJECTED = 'REJECTED'const PENDING = 'PENDING'class Promise {constructor(executor) {this.status = PENDINGthis.value = undefinedthis.reason = undefined// 要点 9: 分别创建一个`队列用来存放成功和失败回调事件this.onfulfilledCallbacks = []this.onrejectedCallbacks = []let resolve = (value) => {if (this.status === PENDING) {this.value = valuethis.status = RESOLVEDthis.onfulfilledCallbacks.forEach(fn => fn()) // 要点 11: 状态变为成功时遍历队列依次执行}}let reject = (reason) => {if (this.status === PENDING) {this.reason = reasonthis.status = REJECTEDthis.onrejectedCallbacks.forEach(fn => fn()) // 要点 11: 状态变为失败时遍历队列依次执行}}try {executor(resolve, reject)} catch(e) {reject(e)}}then(onfulfilled, onrejected) {if(this.status === RESOLVED){onfulfilled(this.value)}if(this.status === REJECTED){onrejected(this.reason)}// console.log(this.status) // PENDING// 要点 8: 定时器执行resolve时,状态仍然是pendingif(this.status === PENDING){// 要点 10: 一个 promise 实例可以被 then 多次,存放 成功回调事件this.onfulfilledCallbacks.push(() => {onfulfilled(this.value)})// 要点 10: 一个 promise 实例可以被 then 多次,存放 失败回调事件this.onrejectedCallbacks.push(() => {onrejected(this.reason)})}}}// Commonjs规范导出模块module.exports = Promise
myPromise — 链式调用(重难点,不好理解)
链式调用这一部分,比较绕,不太好理解,我的老师鼓励我,说:“书读百遍,其义自现”,哈哈哈,现在用来鼓励大家吧!!!test.js。
let Promise = require('./1.myPromise')let p = new Promise((resolve, reject) => {resolve('成功')})// 可以分别注释用例代码,进行效果演示p.then((data) => {return data // 用例1. 返回的是普通值: ‘成功’// throw new Error() // 用例2. 报错或异常: 抛出异常,会直接走下一次then的失败// return new Error() // 用例3. 返回的是普通值: error对象,需要特别注意// return new Promise((s,j)=>s(1)) // 用例4. 返回的是promise: 会传递当前promise的已成功结果// return new Promise((s,j)=>j(1)) // 用例5. 返回的是promise: 会传递当前promise的已失败结果}).then((data) => {console.log(data,2) // 执行结果:用例1, 用例3, 用例4}, (err) => {console.log(err,3) // 执行结果:用例2, 用例5})// 1. 返回的是普通值:不论then是成功还是失败。只要是普通值就传递到下一次then的成功中。(普通值包括:非错误非promise,包括对象)// 2. 报错或异常:一定会走到下一次then的失败中。如果离自己最近的then没有错误处理,会向下找// 3. 特别注意: return new Error()返回的是错误对象,属于普通值走下一次then的成功,而throw new Error() 是抛出异常,会走下一次的失败// 4. 返回的是promise:会采用promise的状态,决定下一次then是成功还是失败,此处会有递归判断// 5. 总结: 如果返回一个普通值,除了promise ,就传递给下一个then的成功,如果返回一个失败的promise或者抛出异常(try catch),会走下一个then的失败
myPromise.js
const RESOLVED = 'RESOLVED'const REJECTED = 'REJECTED'const PENDING = 'PENDING'const resolvePromise = (promise2, x, resolve, reject) => {if (promise2 === x) { // 防止自己等待自己 一直循环等待// 原生返回:return reject(new TypeError('TypeError: Chaining cycle detected for promise #<Promise>'))return reject(new TypeError('我们自己报的错:循环引用报错'))}let called; // 为了兼容其他promise 库符合a+规范,防止状态改变后再次被调用// 考虑其他promise库兼容问题:判断x是不是promise:不是null的对象 || 函数if (x !== null && (typeof x === 'object' || typeof x === 'function')) {try { // 为防止then时 出现异常,Object.definePropertylet then = x.then // 取x 的then 方法/*** 可能对象是{then:{}},还需要判断then是否是函数,* 是函数就认为是promise,并调用then方法*/if (typeof then === 'function') {// call第一个参数是this,后面的是成功回调 和 失败回调// 如果成功回调返回值 y 仍然是promise,就继续递归解析promise,解析到返回值不是一个Promise类型为止// promise2能否成功,是根据x的值来定的,x是promise,那么就要等到x完成,x完成后,如果返回y又是promise,那promise2又要等到y完成then.call(x, y =>{if (called) returncalled = trueresolvePromise(promise2, y, resolve, reject)}, e => {if (called) returncalled = truereject(e)})} else {// 否则就认为 then 是一个普通对象,成功即可resolve(x)}} catch (e) {if (called) returncalled = truereject(e) // 出现异常,直接走失败逻辑}} else { // x 为普通值resolve(x)}}class Promise {constructor(executor) {this.status = PENDINGthis.value = undefinedthis.reason = undefinedthis.onfulfilledCallbacks = []this.onrejectedCallbacks = []let resolve = (value) => {if (this.status === PENDING) {this.value = valuethis.status = RESOLVEDthis.onfulfilledCallbacks.forEach(fn => fn())}}let reject = (reason) => {if (this.status === PENDING) {this.reason = reasonthis.status = REJECTEDthis.onrejectedCallbacks.forEach(fn => fn())}}try {executor(resolve, reject)} catch (e) {reject(e)}}then(onfulfilled, onrejected) {// 要点 12: then链式调用,返回的并不是this,而是一个`新的promise实例`let promise2 = new Promise((resolve, reject) => { // new Promise执行器中的代码是立即执行,因此没有影响if (this.status === RESOLVED) {// 加定时器是因为在当前执行上下文中,不能获取promise2的值setTimeout(() => {// 要点13.2. 用于报错或抛出异常处理,以下同理try {// 要点13:存储第一次then的回调结果返回值,用于下次then的参数传递,以下let x 同理let x = onfulfilled(this.value)// 要点13.3: x 可能会是一个promise, 需要单独处理,// 并将promise2、新的返回值:x 、成功回调resolve 失败回调reject 作为参数传递resolvePromise(promise2, x, resolve, reject)} catch (e) {// 要点13.2. 报错或抛出异常处理,直接走promise2的reject,以下同理reject(e)}})}// 以下逻辑同理if (this.status === REJECTED) {setTimeout(() => {try {let x = onrejected(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}})}if (this.status === PENDING) {// 暂存成功回调队列this.onfulfilledCallbacks.push(() => {setTimeout(() => {try {let x = onfulfilled(this.value)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}})})// 暂存失败回调队列this.onrejectedCallbacks.push(() => {setTimeout(() => {try {let x = onrejected(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}})})}})return promise2 // 要点 12: 返回一个新的promise实例}}// Commonjs规范导出模块module.exports = Promise
myPromise — 值的透传
//原生方法:值的穿透 演示let p = new Promise((resolve,reject)=>{resolve(1)// reject(2) // 同理})p.then().then().then(data=>{console.log(data); // 1})p.then().then().then(null,err=>{console.log(err); // 2})// ----------------------------------------------------------//myPromise:基于以上几部分的实现,我们自己的promise是不支持穿透的,那么看一下演变过程,就很容易写出符合规范的透传const Promise = require('./1.myPromise')let p1 = new Promise((resolve,reject)=>{resolve(1)})let p2 = new Promise((resolve,reject)=>{reject(2) // 同理,})// 相当于, 啥都不写时,感觉像是默认定义了一个函数,不停向下传递,去实现一下吧~p1.then(data => data).then(data => data).then(data =>{console.log(data);})// 相当于, throw err,不停向下传递p2.then(null,err=>{throw err}).then(null,err=>{console.log(err);throw err}).then(null,err=>{console.log(err);})
.........// 在这里这里...其他都不变then(onfulfilled, onrejected) {// onfulfilled 是函数就执行,不是函数包一层函数并直接返回数据onfulfilled = typeof onfulfilled === 'function' ? onfulfilled : v => v;// onrejected 是函数就执行,不是函数包一层函数并直接抛出错误onrejected = typeof onrejected === 'function' ? onrejected : err => { throw err };.........
完美通过官方872条用例
为了测试myPromise库,必须公开一个非常小的适配器接口。可以说是promise的延迟对象defer,下文会详细介绍,各位稍安勿躁。
第一步:找到文件最下面。加上下面几行代码,
/*** ...* 其余不变* ...*/// 测试自己的写的promise 是否符合a+规范// promise的延迟对象Promise.defer = Promise.deferred = function () {let dfd = {}dfd.promise = new Promise((resolve, reject) => {dfd.resolve = resolve;dfd.reject = reject})return dfd;}module.exports = Promise
第二步:安装测试包 npm install promises-aplus-tests -g
第三步:进入对应目录执行 promises-aplus-tests ./1.myPromise.js

name.txt:文件内容是:age.txt
age.txt:文件内容18
const fs = require('fs')const Promise = require('./1.myPromise')function read(filepath){// 想要read方法可以使用then方法,需要包一层new Promisereturn new Promise((resolve,reject)=>{fs.readFile(filepath,'utf8',function(err,data){if(err) return reject(err)resolve(data)})})}read('./name.txt').then(data=>{return read(data) // data = age.txt}).then(data=>{console.log(data); // data = age.txt})
使用延迟对象的写法:
const fs = require('fs')const Promise = require('./1.myPromise')function readDefer(filepath){let dfd = Promise.defer() // 减少一层嵌套fs.readFile(filepath,'utf8',function(err,data){if(err) return dfd.reject(err)dfd.resolve(data)})return dfd.promise}readDefer('./name.txt').then(data=>{return readDefer(data) // data = age.txt}).then(data=>{console.log(data); // data = age.txt})
myPromise.catch
完成以上内容,就已经实现了Promise A+ 规范的全部内容,而我们常用的catch及finally并不属于 A+规范,同样可以实现一下,catch是属于实例上的方法,用于出错处理及捕获异常
演变过程:test.js
const Promise = require('./1.myPromise')new Promise((resolve, reject) => {reject('失败')}).then(data => { // 第一个then没有错误处理方法,直接会传递到第二个then中console.log(data);}).then(null, err => {console.log(err, 'errrrrr'); // 失败 errrrrr})// 将上述代码中null优化一下,于是就有了catch方法new Promise((resolve, reject) => {reject('失败')}).then(data => {console.log(data);}).catch(err => {console.log(err, 'errrrrr'); // 失败 errrrrr})
实现:myPromise.js
class Promise{// 重复代码省略// constructor(){...}// then(){...}catch(onrejected){ // 实例的catchreturn this.then(null,onrejected)}}/*** 其余重复代码省略*/
const Promise = require('./1.myPromise')let p1 = new Promise((resolve, reject) => {setTimeout(() => {// resolve('成功') // 1reject('失败') // 2}, 1000)}).finally(() => {return new Promise((resolve, reject) => {setTimeout(() => {// resolve(1000) // 3 不会采用promise成功的结果,但是会等待执行reject(9000) // 4 但是返回一个失败的promise,会走catch,相当于throw new Error}, 1000)})}).then(data => {console.log(data); // 对应上述不同序号组合,输出结果有所不同,可自行组合实验,下方也会给大家作出总结}).catch(e => {console.log(e, 'catch');})/*** 整理流程:* 组合:* 1+3:成功 + 成功 ,走then=>data 返回 1 返回的数据('成功')* 1+4:成功 + 失败 ,走then=>err 抛出 4 返回的数据(9000)* 2+3:失败 + 成功 ,走then=>err 抛出 2 返回的数据('失败')* 2+4:失败 + 失败 ,走then=>err 抛出 4 返回的数据(9000)*/
实现:myPromise.js
/*** 1. finally 传递了一个方法 callback* 2. finally 方法相当于一个then,特点就是在函数中返回一个promise,并会等待这个promise的完成* 3. Promise.resolve 又会等待 callback执行完成*/class Promise{// 重复代码省略// constructor(){...}// then(){...}// catch(){...}finally(cb){return this.then((data)=>{ // 成功 || 失败 都会执行// Promise.resolve 目的是等待cb() 后的promise完成// 成功时调用finally,直接传递this实例成功的数据data,finally方法本身是没有参数的return Promise.resolve(cb()).then(()=>data)},(err)=>{// 失败时调用finally,等待Promise.resolve(cb())的执行的结果,当cb结果为失败时,直接以失败的结果直接走catch// 而只有在Promise.resolve成功时候,才会去执行.then(()=>{throw err}),抛出this实例reject的err信息return Promise.resolve(cb()).then(()=>{throw err})})}}/*** 其余重复代码省略*/
myPromise.resolve
Promise.resolve() 方法会创造一个成功的promsie,属于类上的方法,通过className调用
演变过程:test.js
const Promise = require('./1.myPromise')Promise.resolve(200).then(data => {console.log(data); // 200})// 等价于new Promise((resolve, reject) => {resolve(200)}).then(data => {console.log(data); // 200})
constructor(executor) {/*** 其余重复无改动*/let resolve = (value) => {// 一个promise直接resolve 另一个promise时,会等待里面的promise执行完,返回成功的执行结果if (value instanceof Promise) {return value.then(resolve, reject)}if (this.status === PENDING) {this.value = valuethis.status = RESOLVEDthis.onfulfilledCallbacks.forEach(fn => fn())}}let reject = (reason) => {// reject 一个promise时,不需要单独处理,失败就直接走失败的逻辑,不用处理其返回值if (this.status === PENDING) {this.reason = reasonthis.status = REJECTEDthis.onrejectedCallbacks.forEach(fn => fn())}}/*** 其余重复无改动*/}static resolve(value) {return new Promise((resolve, reject) => {resolve(value)})}
myPromise.reject
Promise.reject() 方法会创造一个失败的promsie,属于类上的方法,通过className调用。
演变过程:test.js
const Promise = require('./1.myPromise')Promise.reject(100).then(null,err => {console.log(err, 'errrrrr'); // 100 errrrrr})// 等价于new Promise((resolve, reject) => {reject(100)}).then(data=>{console.log(data);},err => {console.log(err, 'errrrrr'); // 100 errrrrr})
实现:myPromise.js
class Promise{/*** 其余重复无改动*/static reject(reason) {return new Promise((resolve, reject) => {reject(reason)})}}/*** 其余重复无改动*/
myPromise.all
Promise.all()方法用于将多个 Promise 实例,包装并返回一个新的 Promise 实例p
p的状态由传递的多个 Promise 决定,分成两种情况。(官网是这样说的)
(1)只有所有promise实例的状态都变成fulfilled,p的状态才会变成fulfilled,此时数组中promise的返回值组成一个数组,传递给p的回调函数。
(2)只要数组的中promise有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
test.js
const Promise = require('./1.myPromise')Promise.all([1, 2, 3,new Promise((resolve, reject) => {setTimeout(() => {resolve('成功')}, 1000)}),new Promise((resolve, reject) => {setTimeout(() => {resolve('成功') // 情况1// reject('失败') // 情况2}, 1000)})]).then(data => {console.log(data); // 情况1. [ 1, 2, 3, '成功', '成功' ]}).catch(err => {console.log(err); // 情况2. 失败})
myPromise.js
class Promise{// 在原有代码基础上,添加一个静态方法static all(promises){return new Promise((resolve,reject)=>{let result = []let times = 0const processSuccess = (index,val)=>{result[index] = valif(++times === promises.length){resolve(result)}}for (let i = 0; i < promises.length; i++) { // 并发。多个请求一起执行let p = promises[i];if(p && typeof p.then === 'function'){ // 判断p是不是promise实例,是则继续等待p的执行结果,处理p对应的成功和失败p.then(data=>{processSuccess(i,data)},reject) // 如果其中一个promise失败了,直接执行失败回调,由于reject本身就是函数,故可简写}else{ // 如果不是promise实例就直接调用成功,并存储该值processSuccess(i,p)}}})}}
myPromise.race
const Promise = require('./1.myPromise')Promise.race([new Promise((resolve, reject) => {setTimeout(() => {resolve('成功')}, 2000)}),new Promise((resolve, reject) => {setTimeout(() => {reject('失败')}, 1000)})]).then(data => {console.log(data);}).catch(err => {console.log(err); // 输出:失败,resolve 2s执行,reject 1s执行,reject更快})
myPromise.js
class Promise{static race(promises){return new Promise((resolve,reject)=>{// for循环执行,只要有一个状态发生改变,就直接将该实例的返回值 返回for (let i = 0; i < promises.length; i++) {let p = promises[i];if(p && typeof p.then === 'function'){p.then(data=>{resolve(data)},reject)}else{resolve(p)}}})}}
const RESOLVED = 'RESOLVED'const REJECTED = 'REJECTED'const PENDING = 'PENDING'const resolvePromise = (promise2, x, resolve, reject) => {if (promise2 === x) {return reject(new TypeError('循环引用报错'))}if (x !== null && (typeof x === 'object' || typeof x === 'function')) {let called;try {let then = x.thenif (typeof then === 'function') {then.call(x, y => {if (called) returncalled = trueresolvePromise(promise2, y, resolve, reject)}, e => {if (called) returncalled = truereject(e)})} else {resolve(x)}} catch (e) {if (called) returncalled = truereject(e)}} else {resolve(x)}}class Promise {constructor(executor) {this.status = PENDINGthis.value = undefinedthis.reason = undefinedthis.onfulfilledCallbacks = []this.onrejectedCallbacks = []let resolve = (value) => {if (value instanceof Promise) {return value.then(resolve, reject)}if (this.status === PENDING) {this.value = valuethis.status = RESOLVEDthis.onfulfilledCallbacks.forEach(fn => fn())}}let reject = (reason) => {if (this.status === PENDING) {this.reason = reasonthis.status = REJECTEDthis.onrejectedCallbacks.forEach(fn => fn())}}try {executor(resolve, reject)} catch (e) {reject(e)}}then(onfulfilled, onrejected) {onfulfilled = typeof onfulfilled === 'function' ? onfulfilled : v => v;onrejected = typeof onrejected === 'function' ? onrejected : err => {throw err};let promise2 = new Promise((resolve, reject) => {if (this.status === RESOLVED) {setTimeout(() => {try {let x = onfulfilled(this.value)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}})}if (this.status === REJECTED) {setTimeout(() => {try {let x = onrejected(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}})}if (this.status === PENDING) {this.onfulfilledCallbacks.push(() => {setTimeout(() => {try {let x = onfulfilled(this.value)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}})})this.onrejectedCallbacks.push(() => {setTimeout(() => {try {let x = onrejected(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}})})}})return promise2}catch (onrejected) {return this.then(null, onrejected)}finally(cb) {return this.then((data) => {return Promise.resolve(cb()).then(() => data)}, (err) => {return Promise.resolve(cb()).then(() => { throw err })})}static resolve(value) {return new Promise((resolve, reject) => {resolve(value)})}static reject(reason) {return new Promise((resolve, reject) => {reject(reason)})}static all(promises) {return new Promise((resolve, reject) => {let result = []let times = 0const processSuccess = (index, val) => {result[index] = valif (++times === promises.length) {resolve(result)}}for (let i = 0; i < promises.length; i++) {let p = promises[i];if (p && typeof p.then === 'function') {p.then(data => {processSuccess(i, data)}, reject)} else {processSuccess(i, p)}}})}static race(promises) {return new Promise((resolve, reject) => {for (let i = 0; i < promises.length; i++) {let p = promises[i];if (p && typeof p.then === 'function') {p.then(data => {resolve(data)}, reject)} else {resolve(p)}}})}}Promise.defer = Promise.deferred = function () {let dfd = {}dfd.promise = new Promise((resolve, reject) => {dfd.resolve = resolve;dfd.reject = reject})return dfd;}module.exports = Promise
Click Me
学习更多技能
请点击下方公众号
![]()

