手写 Promise 源码实现

关乎手写Promise,网上已经有好多相关资料,我也查阅过相关资料,但大多不够全,并且有些没那么易懂,所以自己想从头写个通俗易懂的Promise。

查看完整代码请戳:手写Promise

从零开始,手写 Promise

原生Promise

首先我们看下原先Promise大概有什么功能:
在控制台打印下

console.log(new Promise(
    function(resolve,reject){ })
);

展开结果如下:
原生promise
从控制台输出的Promise对象我们可以清楚的看到Promise对象有以下几种基本方法:
Promise.resolve()
Promise.reject()
Promise.all()
Promise.race()
Promise.prototype.then()
Promise.prototype.catch()
Promise.prototype.finally()

  1. then,catch,finally这三个属于实例方法。
  2. reject,resolve,all,race,这三个属于构造函数里的方法,是静态方法。

Promise/A+

我们想要手写一个 Promise,就要遵循 Promise/A+ 规范,业界所有 Promise 的类库,像是ES6的Promise也好,jQuery的Promise也好都遵循这个规范。

开始手写

一、Promise核心逻辑实现

const promise = new Promise((resolve, reject) => {
   resolve('success')
   reject('err')
})

promise.then(value => {
  console.log('resolve', value)
}, reason => {
  console.log('reject', reason)
})

分析下Promise的基本特征:

  1. Promise 是一个类,在执行这个类的时候会传入一个执行器(executor),这个执行器会立即执行
  2. executor接受两个参数,分别是resolve和reject
  3. Promise 会有三种状态,默认状态是pending 「规范 Promise/A+ 2.1」
    - pending 等待
    - fulfilled 完成
    - rejected 失败
  4. promise 有一个value保存成功状态的值,可以是undefined/thenable/promise;「规范 Promise/A+ 1.3」
  5. promise 有一个reason保存失败状态的值;「规范 Promise/A+ 1.5」
  6. 状态只能由 pending --> fulfilled 或者 pending --> rejected,且一但发生改变便不可二次修改。
  7. Promise 中使用 resolve 和 reject 两个函数来更改状态
  8. then 方法内部做的事情就是状态判断,接收两个参数,分别是Promise成功的回调onFulfilled, 和 promise 失败的回调 onRejected;「规范 Promise/A+ 2.2」
    - 如果状态是成功,调用成功回调函数(onFulfilled),参数是Promise的value;
    - 如果状态是失败,调用失败回调函数(onRejected),参数是Promise的reason;

代码实现:

  1. 新建 CustomPromise 类,传入执行器 executor

    // 新建 CustomPromise.js
    
    // 新建 CustomPromise 类
    class CustomPromise {
      constructor(executor){
        // executor 是一个执行器,进入会立即执行
        executor() 
      }
    }
    
  2. executor 传入 resolve 和 reject 方法作为参数,这样使用方就可以接收到这两个方法并调用

// CustomPromise.js

// 新建 CustomPromise 类
class CustomPromise	{
	constructor(executor) {
		// executor 是一个执行器,进入会立即执行
		// 并传入resolve和reject方法
		executor(this.resolve, this.reject)
	}
	// resolve和reject为什么要用箭头函数?
	// 如果直接调用的话,普通函数this指向的是window或者undefined
	// 用箭头函数就可以让this指向当前实例对象

	// 更改成功后的状态
	resolve = () => {}
	// 更改失败后的状态
	reject = () => {}
}
  1. 状态与结果的管理
// 先定义三个常量表示状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

// 新建 CustomPromise 类
class CustomPromise	{
  constructor(executor){
    // executor 是一个执行器,进入会立即执行
    // 并传入resolve和reject方法
    executor(this.resolve, this.reject)
  }

  // 储存状态的变量,初始值是 pending
  status = PENDING;

  // 成功之后的值
  value = null;
  // 失败之后的原因
  reason = null;

  // 更改成功后的状态
  resolve = (value) => {
    // 状态为 PENDING 时才可以更新状态
    if (this.status === PENDING) {
      // 状态修改为成功
      this.status = FULFILLED;
      // 保存成功之后的值
      this.value = value;
    }
  }

  // 更改失败后的状态
  reject = (reason) => {
    // 状态为 PENDING 时才可以更新状态
    if (this.status === PENDING) {
      // 状态修改为失败
      this.status = REJECTED;
      // 保存失败后的原因
      this.reason = reason;
    }
  }
}
  1. then 的简单实现
// 包含一个 then 方法,并接收两个参数 onFulfilled、onRejected
CustomPromise.prototype.then = function (onFulfilled, onRejected) {
  // 判断状态
  if (this.status === FULFILLED) {
    // 调用成功回调,并且把值返回
    onFulfilled(this.value);
  } else if (this.status === REJECTED) {
    // 调用失败回调,并且把原因返回
    onRejected(this.reason);
  }
}
  1. 使用 module.exports 对外暴露 CustomPromise 类
// CustomPromise.js
module.exports = CustomPromise;

完整代码:

// CustomPromise.js

// 先定义三个常量表示状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

// 新建 CustomPromise 类
class CustomPromise {
	constructor(executor) {
		// executor 是一个执行器,进入会立即执行
		// 并传入resolve和reject方法
		executor(this.resolve, this.reject)
	}

	// 储存状态的变量,初始值是 pending
	status = PENDING

	// 成功之后的值
	value = null
	// 失败之后的原因
	reason = null

	// resolve和reject为什么要用箭头函数?
	// 如果直接调用的话,普通函数this指向的是window或者undefined
	// 用箭头函数就可以让this指向当前实例对象

	// 更改成功后的状态
	resolve = (value) => {
		// 状态为 PENDING 时才可以更新状态
		if (this.status === PENDING) {
			// 状态修改为成功
			this.status = FULFILLED
			// 保存成功之后的值
			this.value = value
		}
	}
	// 更改失败后的状态
	reject = (reason) => {
		// 状态为 PENDING 时才可以更新状态
		if (this.status === PENDING) {
			// 状态修改为失败
			this.status = REJECTED
			// 保存失败后的原因
			this.reason = reason
		}
	}
}
CustomPromise.prototype.then = function (onFulfilled, onRejected) {
	// 判断状态
	if (this.status === FULFILLED) {
		// 调用成功回调,并且把值返回
		onFulfilled(this.value)
	} else if (this.status === REJECTED) {
		// 调用失败回调,并且把原因返回
		onRejected(this.reason)
	}
}
module.exports = CustomPromise

验证下:

// 新建 testCustomPromise.js

// 引入我们的 CustomPromise.js
const CustomPromise = require('./CustomPromise')
const p = new CustomPromise((resolve, reject) => {
	resolve('ok')
	reject('error')
})

p.then(
	(value) => {
		console.info('resolve', value)
	},
	(err) => {
		console.info('reject', err)
	}
)
// 执行结果:resolve ok

执行结果符合我们的预期,第一步完成了,掌声响起来👏👏👏

二、在 Promise 类中支持异步逻辑

接下来的功能都采用测试驱动功能的完善

给测试用例加上异步逻辑,例如:

const CustomPromise = require('./CustomPromise')
const p = new CustomPromise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok')
		reject('error')
	}, 1000)
})

p.then(
	(value) => {
		console.info('resolve', value)
	},
	(err) => {
		console.info('reject', err)
	}
)
// 没有打印信息

分析原因:

主线程代码开始执行,传感器(executor)会立即执行,但由于setTimeout是宏任务,并不会立即执行,也就不会更改status的状态为fulfilled;then会立即执行,此时状态为pending,不会执行成功(onFulfilled)或失败(onRejected)回调函数。

完善功能:
所以需要在then函数里处理下pending状态,改造如下:

  1. 缓存成功或失败回调
	// 存储成功回调函数
	onFulfilledCallback = null
	// 存储失败回调函数
	onRejectedCallback = null
  1. then方法中对pending状态的处理,将回调函数存储
 if (this.status === PENDING) {
	// 因为不知道后面状态的变化情况,所以将成功回调和失败回调存储起来
	// 等到promise状态切为成功或失败时再执行
	this.onFulfilledCallback = onFulfilled
	this.onRejectedCallback = onRejected
}
  1. resolve 与 reject 中调用回调函数
	// 更改成功后的状态
	resolve = (value) => {
		// 状态为 PENDING 时才可以更新状态
		if (this.status === PENDING) {
			// 省略其它...
			// 判断成功回调是否存在,如果存在就调用
			this.onFulfilledCallback && this.onFulfilledCallback(value)
		}
	}
	// 更改失败后的状态
	reject = (reason) => {
		// 状态为 PENDING 时才可以更新状态
		if (this.status === PENDING) {
			// 省略其它...
			// 判断失败回调是否存在,如果存在就调用
			this.onRejectedCallback && this.onRejectedCallback(reason)
		}
	}

这其实就是一个发布订阅模式,先将then里面的两个函数储存起来,在resovle与reject里取出函数,并执行函数。这种收集依赖->触发通知->取出依赖执行的方式,被广泛运用于发布订阅模式的实现。

验证:

const CustomPromise = require('./CustomPromise')
const p = new CustomPromise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok')
		reject('error')
	}, 1000)
})

p.then(
	(value) => {
		console.info('resolve', value)
	},
	(err) => {
		console.info('reject', err)
	}
)
// 等待2秒,弹出resolve ok

三、实现 then 方法多次调用,添加多个处理函数

同样的先看下添加多个then的测试脚本

const CustomPromise = require('./CustomPromise')
const p = new CustomPromise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok')
		reject('error')
	}, 1000)
})

p.then((value) => {
	console.info(1)
	console.info('resolve', value)
})

p.then((value) => {
	console.info(2)
	console.info('resolve', value)
})

p.then((value) => {
	console.info(3)
	console.info('resolve', value)
})
// 3
// resolve ok

现象:
只输出最后一次then函数的结果:3 resolve ok

分析原因:

因为如果是同步回调,那现状的then会直接返回当前的值,不会有问题;但当为异步回调(像上面的setTimeout)时,现如今的then里会将回调函数存储在一个变量里,后面的变量值会覆盖前面的,就会出现只有最后一个then函数的onFulfilled或onRejected得到调用

完善功能:
将then中的回调函数存储在一个数组里,然后在状态切为resolve或rejected时遍历执行

  1. 类中新增两个数组,去掉原先的回调函数变量

    // 存储成功回调函数
    // onFulfilledCallback = null
    onFulfilledCallbacks = []
    // 存储失败回调函数
    // onRejectedCallback = null
    onRejectedCallbacks = []
    
  2. 在then函数中,将回调函数存入数组中

    if (this.status === PENDING) {
    	// 因为不知道后面状态的变化情况,所以将成功回调和失败回调存储起来
    	// 等到promise状态切为成功或失败时再执行
    	// this.onFulfilledCallback = onFulfilled
    	// this.onRejectedCallback = onRejected
    	this.onFulfilledCallbacks.push(onFulfilled)
    	this.onRejectedCallbacks.push(onRejected)
    }
    
  3. 在resolve中遍历调用成功回调、在reject中遍历调用失败回调

// resolve里面将所有成功的回调拿出来执行
if (this.onFulfilledCallbacks.length) {
	this.onFulfilledCallbacks.forEach((fn) => fn(value))
}
// reject里面将所有成功的回调拿出来执行
if (this.onRejectedCallbacks.length) {
	this.onRejectedCallbacks.forEach((reason) => fn(reason))
}

验证:

const CustomPromise = require('./CustomPromise')
const p = new CustomPromise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok')
	}, 1000)
})

p.then((value) => {
	console.info(1)
	console.info('resolve', value)
})

p.then((value) => {
	console.info(2)
	console.info('resolve', value)
})

p.then((value) => {
	console.info(3)
	console.info('resolve', value)
})
// 1
// resolve success
// 2
// resolve success
// 3
// resolve success

四、实现then方法的链式调用

const CustomPromise = require('./CustomPromise')
const p = new CustomPromise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok')
	}, 1000)
})

function other() {
	return new CustomPromise((resolve, reject) => {
		resolve('success')
	})
}
p.then((value) => {
	console.info(1)
	console.info('resolve', value)
	return other()
}).then((value) => {
	console.info(2)
	console.info('resolve', value)
})
// }).then((value) => {
  ^

// TypeError: Cannot read property 'then' of undefined

现象:
报错,TypeError: Cannot read property ‘then’ of undefined

分析原因:
then 是 CustomPromise 实例才能调用的方法,所以要求then函数本身要返回个 CustomePromise 对象,这样才能实现链式调用。另外then方法里 return 一个返回值作为下一个 then 方法的参数,如果是 return 一个 CustomePromise 对象,那么就需要判断它的状态,要等 return 里的 CustomPromise 状态切换了,才继续执行。

功能完善:

CustomPromise.prototype.then = function (onFulfilled, onRejected) {
	// 为了实现链式调用,创建个新的 CustomPromise 对象,并返回
	const promise2 = new CustomPromise((resole, reject) => {
		// 这里的内容在执行器中,会立即执行
		// 判断状态
		if (this.status === FULFILLED) {
			// 调用成功回调,并且把值返回
			const x = onFulfilled(this.value)
			resolvePromise(x, resole, reject)
		} else if (this.status === REJECTED) {
			// 调用失败回调,并且把原因返回
			onRejected(this.reason)
		} else if (this.status === PENDING) {
			// 因为不知道后面状态的变化情况,所以将成功回调和失败回调存储起来
			// 等到promise状态切为成功或失败时再执行
			// this.onFulfilledCallback = onFulfilled
			// this.onRejectedCallback = onRejected
			this.onFulfilledCallbacks.push(onFulfilled)
			this.onRejectedCallbacks.push(onRejected)
		}
	})
	return promise2
}

function resolvePromise(x, resolve, reject) {
	// 判断x是不是 CustomPromise 实例对象
	if (x instanceof CustomPromise) {
		// 执行 x,调用 then 方法,目的是将其状态变为 fulfilled 或者 rejected
		// x.then(value => resolve(value), reason => reject(reason))
		// 简化之后
		x.then(resolve, reject)
	} else {
		// 普通值
		resolve(x)
	}
}
// 1
// resolve ok      
// 2
// resolve2 success

resolvePromise里的resolve与reject是为了将then函数新生成的promise切成fulfilled或rejected,要不然执行下一个then时,就会出现由于新生成的promise状态永远为pending,回调函数不会被调用,至于参数值自然是为了传给下一个then函数

五、then 方法链式调用识别 Promise 是否返回自己

在控制台打印如下:

const promise = new Promise((resolve, reject) => {
  resolve(100)
})
const p1 = promise.then(value => {
  console.log(value)
  return p1
})
// undefined
// editor.csdn.net/:1 Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>

如果 then 方法返回的是自己的 Promise 对象,则会发生循环调用,这个时候程序会报错

功能完善:

将then函数新生成的promise作为参数传入resolvePromise

 // resolvePromise 集中处理,将 新生成的promise 传入
resolvePromise(promise2, x, resolve, reject);
function resolvePromise(promise2, x, resolve, reject) {
  // 如果相等了,说明return的是自己,抛出类型错误并返回
  if (promise2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  if(x instanceof MyPromise) {
    x.then(resolve, reject)
  } else{
    resolve(x)
  }
}

验证:
报错

return p1
^

ReferenceError: Cannot access 'p1' before initialization  

分析原因:
从错误提示说明,我们要等promise2 完成初始化。这里就需要创建一个异步函数去等待promise2完成初始化。
网上大多采用setTimeout,个人建议用queueMicrotask,因为setTimeout为宏任务,而queueMicrotask跟promise是微任务

改造:

// 创建一个微任务等待 promise2 完成初始化
queueMicrotask(() => {
	// 调用成功回调,并且把值返回
	const x = onFulfilled(this.value)
	// 传入 resolvePromise 集中处理
	resolvePromise(promise2, x, resolve, reject)
})  

验证:

const CustomPromise = require('./CustomPromise')
const p = new CustomPromise((resolve, reject) => {
	resolve('ok')
})

const p1 = p.then((value) => {
	console.info(1)
	console.info('resolve', value)
	return p1
})

p1.then(
	(value) => {
		console.info(2)
		console.info('resolve', value)
	},
	(reason) => {
		console.info(reason)
	}
)
// 1
// resolve ok
// TypeError: Chaining cycle detected for promise #<Promise>

六、捕获错误及 then 链式调用其他状态代码补充

  1. 捕获执行器错误
    捕获执行器中的代码,如果执行器中有代码错误,那么 Promise 的状态要变为失败
    功能完善:

    constructor(executor) {
    	// executor 是一个执行器,进入会立即执行
    	// 并传入resolve和reject方法
    	try {
    		executor(this.resolve, this.reject)
    	} catch (error) {
    		// 如果有错误,就直接执行 reject
    		this.reject(error)
    	}
    }
    

    验证:

    const CustomPromise = require('./CustomPromise')
    const p = new CustomPromise((resolve, reject) => {
    	throw new Error('执行器错误')
    })
    
    p.then(
    	(value) => {
    		console.info(1)
    		console.info('resolve', value)
    	},
    	(reason) => {
    		console.info(2)
    		console.info(reason.message)
    	}
    )
    // 2
    // 执行器错误
    
  2. then执行时的错误捕获
    功能完善:

    // 创建一个微任务等待 promise2 完成初始化
    queueMicrotask(() => {
    	try {
    		// 调用成功回调,并且把值返回
    		const x = onFulfilled(this.value)
    		// 传入 resolvePromise 集中处理
    		resolvePromise(promise2, x, resolve, reject)
    	} catch (err) {
    		reject(err)
    	}
    })
    

    验证:

    const CustomPromise = require('./CustomPromise')
    const p = new CustomPromise((resolve, reject) => {
    	resolve('ok')
    })
    
    p.then(
    	(value) => {
    		console.info(1)
    		console.info('resolve', value)
    		throw new Error('callback error')
    	},
    	(reason) => {
    		console.info(2)
    		console.info(reason.message)
    	}
    ).then(
    	(value) => {
    		console.info(3)
    		console.info(value)
    	},
    	(err) => {
    		console.info(4)
    		console.info(err.message)
    	}
    )
    // 1
    // resolve ok
    // 4
    // callback error
    
    

七、参考fulfilled 状态下的处理方式,对 rejected 和 pending 状态进行改造

功能完善:

CustomPromise.prototype.then = function (onFulfilled, onRejected) {
	// 为了实现链式调用,创建个新的 CustomPromise 对象,并返回
	const promise2 = new CustomPromise((resolve, reject) => {
		// 这里的内容在执行器中,会立即执行
		const fulfilledMicrotask = () => {
			// 创建一个微任务等待 promise2 完成初始化
			queueMicrotask(() => {
				try {
					// 调用成功回调,并且把值返回
					const x = onFulfilled(this.value)
					// 传入 resolvePromise 集中处理
					resolvePromise(promise2, x, resolve, reject)
				} catch (err) {
					reject(err)
				}
			})
		}

		const rejectedMicrotask = () => {
			// 创建一个微任务等待 promise2 完成初始化
			queueMicrotask(() => {
				try {
					// 调用失败回调,并且把原因返回
					const x = onRejected(this.reason)
					// 传入 resolvePromise 集中处理
					resolvePromise(promise2, x, resolve, reject)
				} catch (err) {
					reject(err)
				}
			})
		}
		// 判断状态
		if (this.status === FULFILLED) {
			fulfilledMicrotask()
		} else if (this.status === REJECTED) {
			rejectedMicrotask()
		} else if (this.status === PENDING) {
			this.onFulfilledCallbacks.push(fulfilledMicrotask)
			this.onRejectedCallbacks.push(rejectedMicrotask)
		}
	})
	return promise2
}

验证:

const CustomPromise = require('./CustomPromise')
const p = new CustomPromise((resolve, reject) => {
	resolve('ok')
})

p.then(
	(value) => {
		console.info(1)
		console.info('resolve', value)
		throw new Error('callback error')
	},
	(reason) => {
		console.info(2)
		console.info(reason.message)
	}
)
	.then(
		(value) => {
			console.info(3)
			console.info(value)
		},
		(err) => {
			console.info(4)
			console.info(err.message)
			return err.message
		}
	)
	.then((value) => {
		console.info(5)
		console.info(value)
		throw new Error('err') // 进入下一个then里的onRejected
		// return new Error('err') // 进入下一个then里的onFulfilled
	})
	.then(
		(value) => {
			console.info(6)
			console.info(value)
		},
		(err) => {
			console.info(7)
			console.info(err.message)
		}
	)
// 1
// resolve ok
// 4
// callback error
// 5
// callback error
// 7
// err

八、then中的参数变为可选(即实现值传递)

当不传入onFulfilled回调函数时,默认为value=>value
当不传入onRejected回调函数时,默认为reason => {throw reason}

功能完善:

CustomPromise.prototype.then = function (onFulfilled, onRejected) {
	// 如果不传,就使用默认函数
	onFulfilled =
		typeof onFulfilled === 'function' ? onFulfilled : (value) => value
	onRejected =
		typeof onRejected === 'function'
			? onRejected
			: (reason) => {
					throw reason
			  }
}

验证:

const CustomPromise = require('./CustomPromise')
const p = new CustomPromise((resolve, reject) => {
	resolve('ok')
})
p.then()
	.then()
	.then((value) => console.log(value))
// ok
const MyPromise = require('./MyPromise')
const promise = new MyPromise((resolve, reject) => {
  reject('err')
})
 
promise.then().then().then(value => console.log(value), reason => console.log(reason))
// err

九、实现 resolve 与 reject 的静态调用

const CustomPromise = require('./CustomPromise')
CustomPromise.resolve()
	.then(() => {
		console.log(0)
		return CustomPromise.resolve(4)
	})
	.then((res) => {
		console.log(res)
	})
// CustomPromise.resolve()
//               ^

// TypeError: CustomPromise.resolve is not a function

结果不出意外的报错了,因为根本没有定义这些静态方法
功能完善:

// resolve 静态方法
static resolve(parameter) {
	// 如果传入 CustomPromise 就直接返回
	if (parameter instanceof CustomPromise) {
		return parameter
	}

	// 转成常规方式
	return new CustomPromise((resolve) => {
		resolve(parameter)
	})
}

// reject 静态方法
static reject(reason) {
	return new CustomPromise((resolve, reject) => {
		reject(reason)
	})
}

验证:

const CustomPromise = require('./CustomPromise')
CustomPromise.resolve()
	.then(() => {
		console.log(0)
		return CustomPromise.resolve(4)
	})
	.then((res) => {
		console.log(res)
	})
// 0
// 4

九、补齐 Promise 的API

  1. catch
    Promise.prototype.catch 用来捕获 promise 的异常,就相当于一个没有成功的 then。

功能完善:

CustomPromise.prototype.catch = function (errCallback) {
	return this.then(null, errCallback)
}

验证:

const CustomPromise = require('./CustomPromise')
CustomPromise.resolve(
	new CustomPromise((resolve, reject) => {
		setTimeout(() => {
			reject('fail')
		}, 1000)
	})
)
	.then((value) => {
		console.info(value, 'value')
	})
	.catch((err) => {
		console.info(err, 'err')
	})
// fail err
  1. finally
    finally不是最终的意思,而是无论如何都会执行的意思。相当于要在then的成功与失败回调里都要执行finally的回调函数
    如果是进入then的成功回调,则要将结果返回;
    如果是进入then的失败回调,则要将失败结果传到catch中。
    功能完善:
CustomPromise.prototype.finally = function (callback) {
	return this.then(
		(value) => {
			return CustomPromise.resolve(callback()).then(() => value)
		},
		(reason) => {
			return CustomPromise.resolve(callback()).then(() => {
				throw reason
			})
		}
	)
}

验证:

CustomPromise.resolve(456)
	.finally(() => {
		return new CustomPromise((resolve, reject) => {
			setTimeout(() => {
				resolve(123)
			}, 3000)
		})
	})
	.then((data) => {
		console.log(data, 'success')
	})
	.catch((err) => {
		console.log(err, 'error')
	})
// 456 success
  1. all
    promise.all 是解决并发问题的,多个异步并发获取最终的结果(如果有一个失败则失败)
    功能完善:
CustomPromise.all = function (values) {
	if (!Array.isArray(values)) {
		const type = typeof values
		return new TypeError(`TypeError: ${type} ${values} is not iterable`)
	}

	return new CustomPromise((resolve, reject) => {
		let resultArr = []
		let orderIndex = 0
		const processResultByKey = (value, index) => {
			resultArr[index] = value
			if (++orderIndex === values.length) {
				resolve(resultArr)
			}
		}
		for (let i = 0; i < values.length; i++) {
			let value = values[i]
			if (value && typeof value.then === 'function') {
				value.then((value) => {
					processResultByKey(value, i)
				}, reject)
			} else {
				processResultByKey(value, i)
			}
		}
	})
}

验证:

const CustomPromise = require('./CustomPromise')
let p1 = new CustomPromise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok1')
	}, 1000)
})

let p2 = new CustomPromise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok2')
	}, 1000)
})

CustomPromise.all([1, 2, 3, p1, p2]).then(
	(data) => {
		console.log('resolve', data)
	},
	(err) => {
		console.log('reject', err)
	}
)
// 1s 后输出
// resolve [ 1, 2, 3, 'ok1', 'ok2' ]
  1. race
    功能完善:
static race(promises) {
	return new CustomPromise((resolve, reject) => {
		// 一起执行就是for循环
		for (let i = 0; i < promises.length; i++) {
			let val = promises[i]
			if (val && typeof val.then === 'function') {
				val.then(resolve, reject)
			} else {
				// 普通值
				resolve(val)
			}
		}
	})
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值