本文包含以下内容:
- 简单Promise的实现
- 链式调用
- Promise.all
- Promise.resolve
- Promise finally
- Promise catch
1. 简单Promise的实现
只需要实现下面几个常用部分即可
-
- 构造函数 - 可以传入传入回调函数。并提供resolve/reject函数更新内部状态
-
- then - 注册异步成功和失败回调函数,如果状态修改了就立即执行
-
- resolve/reject - 内部更新状态,并执行注册的异步成功和失败回调函数
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
/**
* 1. 构造函数 - 可以传入传入回调函数。并提供resolve/reject函数更新内部状态
* 2. then - 注册异步成功和失败回调函数,如果状态修改了就立即执行
* 3. resolve/reject - 内部更新状态,并执行注册的异步成功和失败回调函数
*/
class Promise2 {
/** 当前状态 */
private status: string = PENDING;
/** 成功值 */
private value: any = null;
/** 失败原因 */
private reason: any = null;
/** 异步方法缓存,当状态改变后执行 */
private FULFILLED_CALLBACK: Function | null = null;
private REJECTED_CALLBACK: Function | null = null;;
constructor(callback: Function) {
callback(this.resolve, this.reject)
}
public resolve = (value: any) => {
if (this.status !== PENDING) {
return
}
this.status = FULFILLED
this.value = value
// 异步执行
this.FULFILLED_CALLBACK?.(this.value);
}
public reject = (reason: any) => {
if (this.status !== PENDING) {
return
}
this.status = REJECTED
this.reason = reason
// 异步执行
this.REJECTED_CALLBACK?.(this.reason);
}
public then(successCallback: Function, errorCallback: Function) {
this.FULFILLED_CALLBACK = successCallback;
this.REJECTED_CALLBACK = errorCallback;
// 如果已经结束则立即执行
if (this.status === FULFILLED) {
successCallback(this.value)
} else if (this.status === REJECTED) {
errorCallback(this.reason)
}
}
}
export default Promise2;
测试:
const promise = new Promise2((resolve: Function, reject: Function) => {
setTimeout(() => {
resolve('new promise')
}, 1000)
// reject('reaspn')
})
promise.then((res: any) => {
console.log(res); // new promise
}, (reason: any) => {
console.log(reason);
})
2. 链式调用
不管 new Promise 创建出来的执行状态是成功 / 失败,只要在 then / catch方法中通过 return 返回一个结果,不管这个值是 Promise 对象还是普通值,都可以通过链式调用的 .then 方法中获取到这个值,因为 promise.then 方法会默认在返回值的外层包裹一层 Promise 对象,这样才可以实现 Promise 一直通过 .then 的方式去链式调用。
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
/**
* 判断执行完的函数返回结果是否为 Promise 对象
* 1. Promise 对象 - .then方法传入resolve, reject进行返回
* 2. 普通值 - resolve返回
*/
function isPromise2(result: any, resolve: Function, reject: Function) {
if (result instanceof Promise2) {
result.then(resolve, reject)
} else {
resolve(result)
}
}
/**
* // 有一点没看懂的就是this ??
*/
class Promise2 {
/** 当前状态 */
private status: string = PENDING;
/** 成功值 */
private value: any = null;
/** 失败原因 */
private reason: any = null;
/** 异步方法缓存,当状态改变后执行 */
private fulfilledList: Function[] = []
private rejectedList: Function[] = []
constructor(callback: Function) {
callback(this.resolve, this.reject)
}
public resolve = (value: any) => {
if (this.status !== PENDING) {
return
}
this.status = FULFILLED
this.value = value
// 多个then注册的方法依次执行掉
while (this.fulfilledList.length) {
this.fulfilledList.shift()?.()
}
}
public reject = (reason: any) => {
if (this.status !== PENDING) {
return
}
this.status = REJECTED
this.reason = reason
// 多个then注册的方法依次执行掉
while (this.rejectedList.length) {
this.rejectedList.shift()?.()
}
}
// then返回一个新的Promise
public then(successCallback: Function, errorCallback?: Function) {
const _this = this;
// ? 为何这里new Promise2会带有之前的this信息
return new Promise2((resolve: Function, reject: Function) => {
// ? 这里的this为何不是新对象的this而是外面的this
console.log(_this === this)// true
if (this.status === FULFILLED) {
// 增加一个 setTimeout 的原因是把当前任务放到下一个宏任务里去执行
// 因为处理异步可能会有问题
setTimeout(() => {
try {
let result = successCallback(this.value)
isPromise2(result, resolve, reject)
} catch (error) {
reject(error)
}
})
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let result = errorCallback?.(this.value)
isPromise2(result, resolve, reject)
} catch (error) {
reject(error)
}
})
} else {
this.fulfilledList.push(() => {
setTimeout(() => {
try {
let result = successCallback(this.value)
isPromise2(result, resolve, reject)
} catch (error) {
reject(error)
}
})
})
this.rejectedList.push(() => {
setTimeout(() => {
try {
let result = errorCallback?.(this.value)
isPromise2(result, resolve, reject)
} catch (error) {
reject(error)
}
})
})
}
})
}
}
export default Promise2;
测试
const promise = new Promise2((resolve: Function, reject: Function) => {
resolve('new promise111111')
})
promise
.then(
(res: any) => {
console.log(res); // 返回值 new promise111111
return '链式调用的方式'
}, (reason: any) => {
console.log(reason);
}
)
.then((value: any) => {
console.log(value); // 返回值 链式调用的方式
})
3. Promise.all
多个成功或一个失败结果的收集,放一个Promise中处理。
// 在一个Promise中处理。如果完成就addData否则reject
static all(arr: Promise2[]) {
// 创建一个保存所有结果的list
let resultList: any[] = []
const len = arr.length
let index = 0
// 返回一个 Promise 对象,让外部可以调用 then 方法获取结果
return new Promise2((resolve: Function, reject: Function) => {
// 保存结果
function addData(key: any, value: any) {
resultList[key] = value
index++
if (index === len) {
resolve(resultList)
}
}
// 循环执行传入的回调函数获取返回结果
for (let i = 0; i < len; i++) {
// 判断当前项,是否为一个 Promise 对象, 如果是, 调用它的then方法获取返回结果
if (arr[i] instanceof Promise2) {
arr[i].then((value: any) => addData(i, value), (reason: any) => reject(reason))
} else {
// 是普通对象的话, 直接返回结果
addData(i, arr[i])
}
}
})
}
测试
// case3:Promise2.all
Promise2.all([1, promise, '100']).then((value: any) => {
console.log(value);
}, (reason: any) => {
console.log(reason);
})
4. Promise.resolve
- 在 resolve 判断当前传入参数是否为 Promsie 对象,是 Promise 的话, 直接返回这个参数
- 如果是普通值的话,创建一个 Promise 对象,调用 promise 的 resolve 参数返回传入的值
static resolve(value: any) {
if (value instanceof Promise2) return value
return new Promise2((resolve: Function) => {
resolve(value)
})
}
测试
Promise2.resolve('test').then((value: any) => {
console.log(value);
});
5. Promise.finally
- 调用当前 Promise 的 then 方法返回一个新的 Promise 对象(保证链式调用)
- 调用 Promise 中的 resolve 方法进行返回
// 1. 调用当前 Promise 的 then 方法返回一个新的 Promise 对象(保证链式调用)
// 2. 调用 Promise 中的 resolve 方法进行返回
public finally(callback: Function) {
return this.then(
(value: any) => this.resolve(callback()).then(() => value),
(reason: any) =>
this.resolve(callback()).then(() => {
throw reason;
})
);
}
测试
new Promise2((resolve, reject) => {
resolve('成功')
// reject('失败')
}).then(res => {
console.log(res, 'resolve2');
}, reason => {
console.log(reason, 'reject2');
}).finally(() => {
console.log('执行了finally方法2');
})
6. Promise.catch
只执行reject就行了
public catch(cb: Function) {
this.then(undefined, cb)
}
测试
new Promise2((resolve, reject) => {
reject('失败')
}).catch(e => {
console.log(e)
})
完整代码
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
/**
* 判断执行完的函数返回结果是否为 Promise 对象
* 1. Promise 对象 - .then方法传入resolve, reject进行返回
* 2. 普通值 - resolve返回
*/
function isPromise2(result: any, resolve: Function, reject: Function) {
if (result instanceof Promise2) {
result.then(resolve, reject)
} else {
resolve(result)
}
}
/**
* 1. 构造函数 - 可以传入传入回调函数。并提供resolve/reject函数更新内部状态
* 2. then - 注册异步成功和失败回调函数,如果状态修改了就立即执行
* 3. resolve/reject - 内部更新状态,并执行注册的异步成功和失败回调函数
*/
class Promise2 {
/** 当前状态 */
private status: string = PENDING;
/** 成功值 */
private value: any = null;
/** 失败原因 */
private reason: any = null;
/** 异步方法缓存,当状态改变后执行 */
private fulfilledList: Function[] = []
private rejectedList: Function[] = []
constructor(callback: Function) {
callback(this.resolve, this.reject)
}
public resolve = (value: any) => {
if (this.status !== PENDING) {
return
}
this.status = FULFILLED
this.value = value
// 多个then注册的方法依次执行掉
while (this.fulfilledList.length) {
this.fulfilledList.shift()?.()
}
}
public reject = (reason: any) => {
if (this.status !== PENDING) {
return
}
this.status = REJECTED
this.reason = reason
// 多个then注册的方法依次执行掉
while (this.rejectedList.length) {
this.rejectedList.shift()?.()
}
}
// 1. 调用当前 Promise 的 then 方法返回一个新的 Promise 对象(保证链式调用)
// 2. 调用 Promise 中的 resolve 方法进行返回
public finally(callback: Function) {
return this.then(
(value: any) => this.resolve(callback()).then(() => value),
(reason: any) =>
this.resolve(callback()).then(() => {
throw reason;
})
);
}
// then返回一个新的Promise
public then(successCallback?: Function, errorCallback?: Function) {
const _this = this;
// ? 为何这里new Promise2会带有之前的this信息
return new Promise2((resolve: Function, reject: Function) => {
// ? 这里的this为何不是新对象的this而是外面的this
console.log(_this === this)// true
if (this.status === FULFILLED) {
// 增加一个 setTimeout 的原因是把当前任务放到下一个宏任务里去执行
// 因为处理异步可能会有问题
setTimeout(() => {
try {
let result = successCallback?.(this.value)
isPromise2(result, resolve, reject)
} catch (error) {
reject(error)
}
})
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let result = errorCallback?.(this.reason)
isPromise2(result, resolve, reject)
} catch (error) {
reject(error)
}
})
} else {
this.fulfilledList.push(() => {
setTimeout(() => {
try {
let result = successCallback(this.value)
isPromise2(result, resolve, reject)
} catch (error) {
reject(error)
}
})
})
this.rejectedList.push(() => {
setTimeout(() => {
try {
let result = errorCallback?.(this.reason)
isPromise2(result, resolve, reject)
} catch (error) {
reject(error)
}
})
})
}
})
}
public catch(cb: Function) {
this.then(undefined, cb)
}
// 在一个Promise中处理。如果完成就addData否则reject
static all(arr: any[]) {
// 创建一个保存所有结果的list
let resultList: any[] = []
const len = arr.length
let index = 0
// 返回一个 Promise 对象,让外部可以调用 then 方法获取结果
return new Promise2((resolve: Function, reject: Function) => {
// 保存结果
function addData(key: any, value: any) {
resultList[key] = value
index++
if (index === len) {
resolve(resultList)
}
}
// 循环执行传入的回调函数获取返回结果
for (let i = 0; i < len; i++) {
// 判断当前项,是否为一个 Promise 对象, 如果是, 调用它的then方法获取返回结果
if (arr[i] instanceof Promise2) {
arr[i].then((value: any) => addData(i, value), (reason: any) => reject(reason))
} else {
// 是普通对象的话, 直接返回结果
addData(i, arr[i])
}
}
})
}
// 对普通值和Promise分别处理
static resolve(value: any) {
if (value instanceof Promise2) return value
return new Promise2((resolve: Function) => {
resolve(value)
})
}
}
本文主要参考 Promise的实现原理系列