3.1 定义整体结构
// 自定义Promise函数模块: IIFE
(function (window) {
// Promise构造函数 excutor: 执行器函数(同步执行)
function Promise(excutor) {
}
// Promise原型对象的then()指定成功和失败的回调函数,返回一个新的promise对象
Promise.prototype.then = function (onResolved, onRejected) {
}
// Promise原型对象的catch()指定失败的回调函数,返回一个新的promise对象
Promise.prototype.catch = function (onRejected) {
}
// Promise函数对象的resolve方法 返回一个指定结果的成功的promise
Promise.resolve = function (value) {
}
// Promise函数对象的reject方法 返回一个指定reason的失败的promise
Promise.reject = function (reason) {
}
// Promise函数对象的all方法 返回一个promise, 只有当所有proimse都成功时才成功, 否则只要有一个失败的就失败
Promise.all = function (promises) {
}
// Promise函数对象的race方法 返回一个promise, 其结果由第一个完成的promise决定
Promise.race = function (promises) {
}
// 向外暴露Promise函数
window.Promise = Promise
})(window)
3.2 Promise构造函数的实现
当我们使用new 创建一个promsie实例对象时,给Promise构造函数传入了一个excutor函数,并且excutor函数中包含onResolve 和 onReject 回调函数。
function Promise(excutor) {
function resolve (value) {
}
function reject (reason) {
}
// 立即执行excutor函数
excutor(resolve,reject)
}
3.2.1 定义promise的状态
Promise中有3种状态,pending,resolved,rejected,那么Promsie中会有一个status用于存储状态;
// 自定义Promise函数模块: IIFE
const PENDING = 'pending'
const RESOLVED = 'resovled'
const REJECTED = 'rejected'
(function (window) {
// Promise构造函数 excutor: 执行器函数(同步执行)
function Promise(excutor) {
}
// 向外暴露Promise函数
window.Promise = Promise
})(window)
3.2.2 定义存储结果的属性和存储回调函数的属性
状态的改变只有一次,resolve函数中称之为value,rejecte函数中我们称之为reason,所以我们只需一个属性变量用于存储结果数据;回调函数在状态改变后指定,也有可能在状态改变前指定,所以我们需要一个数组变量用来存储回调函数。
function Promise(excutor) {
// 将当前promise对象保存起来
const self = this
self.status = PENDING // 给promise对象指定status属性, 初始值为pending
self.data = undefined // 给promise对象指定一个用于存储结果数据的属性
self.callbacks = [] // 每个元素的结构: { onResolved() {}, onRejected() {}}
}
3.2.3 resolve函数实现
function resolve (value) {
// 如果当前状态不是pending, 直接结束
if (self.status!==PENDING) {
return
}
// 将状态改为resolved
self.status = 'resolved'
// 保存value数据
self.data = value
// 如果有待执行callback函数, 立即异步执行回调函数onResolved
if (self.callbacks.length>0) {
setTimeout(() => { // 放入队列中执行所有成功的回调
self.callbacks.forEach(calbacksObj => {
calbacksObj.onResolved(value)
})
});
}
}
3.2.4 reject 函数实现
function reject (reason) {
// 如果当前状态不是pending, 直接结束
if (self.status!==PENDING) {
return
}
// 将状态改为rejected
self.status = REJECTED
// 保存value数据
self.data = reason
// 如果有待执行callback函数, 立即异步执行回调函数onRejected
if (self.callbacks.length>0) {
setTimeout(() => { // 放入队列中执行所有成功的回调
self.callbacks.forEach(calbacksObj => {
calbacksObj.onRejected(reason)
})
});
}
}
3.2.5 执行器异常处理
当我们抛出一个异常时,promsie的状态也会变为 rejected,因此我们要对excutor函数进行try--catch处理
function Promise(excutor) {
function resolve (value) {
}
function reject (reason) {
}
// 立即执行excutor函数
try {
excutor(resolve, reject)
} catch (error) { // 如果执行器抛出异常, promise对象变为rejected状态
reject(error)
}
}
3.3 Promise.prototype.then实现
基础结构
Promise.prototype.then = function(onResolved, onRejected) {
const self = this
return new Promise((resolve, reject) => {
// 如果当前是pending状态,把回调函数保存起来
if(self.status === PENDING) {
self.callbacks.push({
onResolved,
onRejected
})
} else if(self.status === RESOLVED) {
} else { // rejected
}
})
}
3.3.1 如果执行的resolve回调
- 如果抛出异常, return的promise就会失败, reason就是error
- 如果回调函数返回不是promise, return的promise就会成功, value就是返回的值
- 如果回调函数返回是promise, return的promise结果就是这个promise的结果
Promise.prototype.then = function(onResolved, onRejected) {
const self = this
return new Promise((resolve, reject) => {
// 如果当前是pending状态,把回调函数保存起来
if(self.status === PENDING) {
self.callbacks.push({
onResolved,
onRejected
})
} else if(self.status === RESOLVED) {
setTimeout(() => {
try{
const result = onResolved(self.data)
if(result intanceof Promise) {
// 如果回调函数返回是promise, return的promise结果就是这个promise的结果
result.then(
value => resolve(value), // 当result成功时,让return的promise也成功
reason => reject(reason) // 当result失败时,让return的promise也失败
)
}else {
// 如果回调函数返回不是promise, return的promise就会成功, value就是返回的值
resolve(self.data)
}
} catch(error) {
// 如果抛出异常, return的promise就会失败, reason就是error
reject(error)
}
})
} else { // rejected
}
})
}
3.3.2 如果执行的reject回调
当then方法中执行reject回调,返回的promise对象跟在执行resolve回调时情况类似
Promise.prototype.then = function(onResolved, onRejected) {
const self = this
return new Promise((resolve, reject) => {
// 如果当前是pending状态,把回调函数保存起来
if(self.status === PENDING) {
self.callbacks.push({
onResolved,
onRejected
})
} else if(self.status === RESOLVED) {
} else { // rejected
setTimeout(() => {
try{
const result = onRejected(self.data)
if(result intanceof Promise) {
// 如果回调函数返回是promise, return的promise结果就是这个promise的结果
result.then(
value => resolve(value), // 当result成功时,让return的promise也成功
reason => reject(reason) // 当result失败时,让return的promise也失败
)
}else {
// 如果回调函数返回不是promise, return的promise就会成功, value就是返回的值
resolve(self.data)
}
} catch(error) {
// 如果抛出异常, return的promise就会失败, reason就是error
reject(error)
}
})
}
})
}
3.3.3 如果是pending状态时
当前promise的状态是pending时,先把回调函数存起来,以供后续状态改变时使用;当调用resolve回调时,情况与3.3.1中执行的resolve回调保持一致;当调用rejecte回调时,情况与3.3.2中执行的reject回调保持一致;
Promise.prototype.then = function(onResolved, onRejected) {
const self = this
return new Promise((resolve, reject) => {
// 如果当前是pending状态,把回调函数保存起来
if(self.status === PENDING) {
self.callbacks.push({
onResolved(){
try{
const result = onResolved(self.data)
if(result intanceof Promise) {
// 如果回调函数返回是promise, return的promise结果就是这个promise的结果
result.then(
value => resolve(value), // 当result成功时,让return的promise也成功
reason => reject(reason) // 当result失败时,让return的promise也失败
)
}else {
// 如果回调函数返回不是promise, return的promise就会成功, value就是返回的值
resolve(self.data)
}
} catch(error) {
// 如果抛出异常, return的promise就会失败, reason就是error
reject(error)
}
},
onRejected(){
try{
const result = onRejected(self.data)
if(result intanceof Promise) {
// 如果回调函数返回是promise, return的promise结果就是这个promise的结果
result.then(
value => resolve(value), // 当result成功时,让return的promise也成功
reason => reject(reason) // 当result失败时,让return的promise也失败
)
}else {
// 如果回调函数返回不是promise, return的promise就会成功, value就是返回的值
resolve(self.data)
}
} catch(error) {
// 如果抛出异常, return的promise就会失败, reason就是error
reject(error)
}
}
} else if(self.status === RESOLVED) {
} else { // rejected
}
})
}
3.3.4 抽取改变状态的handle方法
上述中我们发现有好多重复代码,因此我们可以把执行状态函数的操作抽取出来
Promise.prototype.then = function(onResolved, onRejected) {
const self = this
return new Promise((resolve, reject) => {
function handle(callback) {
try {
const result = callback(self.data)
// 3. 如果回调函数返回是promise, return的promise结果就是这个promise的结果
if (result instanceof Promise) {
result.then(
value => resolve(value), // 当result成功时, 让 return的promise也成功
reason => reject(reason) // 当result失败时, 让 return的promise也失败
)
} else {
// 3. 如果回调函数返回不是promise, return的promise就会成功, value就是返回的值
resolve(result)
}
} catch (error) {
// 1. 如果抛出异常, return的promise就会失败, reason就是error
reject(error)
}
}
// 如果当前是pending状态,把回调函数保存起来
if(self.status === PENDING) {
self.callbacks.push({
onResolved() {
// 如果当前是resolved状态, 异步执行onResolved并改变return的promise状态
handle(onResolve)
}
onRejected() {
// 如果当前是rejected状态, 异步执行onRejected并改变return的promise状态
handle(onReject)
}
})
} else if(self.status === RESOLVED) {
setTimeout(() => {
handle(onResolved)
})
} else { // rejected
setTimeout(() => {
handle(onRejected)
})
}
})
}
3.3.5 then方法的回调默认值
then方法中回调函数会有不传的情况
Promise.prototype.then = function(onResolved, onRejected) {
onResolved = typeof onResolved==='function' ? onResolved : value => value // 向后传递成功的value
// 指定默认的失败的回调(实现错误/异常传透的关键点)
onRejected = typeof onRejected==='function' ? onRejected : reason => {throw reason} // 向后后传递失败的reason
const self = this
return new Promise((resolve, reject) => {
}
}
3.4 Promise.prototype.catch实现
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected)
}
3.4 Promise.resolve 实现
Promise.resolve = function (value) {
// 返回一个成功/失败的promise
return new Promise((resolve, reject) => {
// value是promise
if (value instanceof Promise) { // 使用value的结果作为promise的结果
value.then(resolve, reject)
} else { // value不是promise => promise变为成功, 数据是value
resolve(value)
}
})
}
3.5 Promise.reject 实现
Promise.reject = function (reason) {
// 返回一个失败的promise
return new Promise((resolve, reject) => {
reject(reason)
})
}
3.6 Promise.race 实现
Promise.race = function (promises) {
// 返回一个promise
return new Promise((resolve, reject) => {
// 遍历promises获取每个promise的结果
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => {// 一旦有成功了, 将return变为成功
resolve(value)
},
reason => { // 一旦有失败了, 将return变为失败
reject(reason)
}
)
})
})
}
3.7 Promise.all 实现
Promise.all = function (promises) {
// 用来保存所有成功value的数组
const values = new Array(promises.length)
// 用来保存成功promise的数量
let resolvedCount = 0
// 返回一个新的promise
return new Promise((resolve, reject) => {
// 遍历promises获取每个promise的结果
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => {
resolvedCount++ // 成功的数量加1
// p成功, 将成功的vlaue保存vlaues
// values.push(value)
values[index] = value
// 如果全部成功了, 将return的promise改变成功
if (resolvedCount===promises.length) {
resolve(values)
}
},
reason => { // 只要一个失败了, return的promise就失败
reject(reason)
}
)
})
})
}
Promise.prototype.finally
当finally 返回一个rejeced 状态的promise对象时,依然可以支持链式调用。当finally 返回一个 resolved 状态的 promise对象 或 非 promise对象时,不支持链式调用
Promise.prototype.finally = function (onFinally) {
return this.then(
value => Promise.resolve(onFinally()).then(() => value),
reason => Promise.resolve(onFinally()).then(() => { throw reason })
)
}