自己动手实现Promise
实现了以下方法
- Promise 的含义
- 基本用法
- Promise.prototype.then()
- Promise.prototype.catch()
- Promise.prototype.finally()
- Promise.all()
- Promise.race()
- Promise.allSettled()
- Promise.any()
- Promise.resolve()
- Promise.reject()
- Promise.try()
参考
简介
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise对象有以下两个特点。
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
优点
- Promise 是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理和更强大。
- 链式操作相对于回调函数体验更好。
缺点
- 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
- 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
- 当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
实现基本功能(then、catch)
// 私有变量,三个状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
/**
* 自己实现Promise
*/
class MyPromise {
constructor(calllback) {
// 状态
this.status = PENDING;
// 值
this.value = undefined;
// 成功回调列表
this.resolveList = [];
// 失败回调列表
this.rejectList = [];
const resolve = (value) => {
// 状态仅允许修改一次
if (this.status !== PENDING){
return;
}
setTimeout(() => {
this.value = value;
this.status = FULFILLED;
for (const func of this.resolveList) {
func(this.value);
}
}, 0);
}
const reject = (reason) => {
// 状态仅允许修改一次
if (this.status !== PENDING){
return;
}
setTimeout(() => {
this.value = reason;
this.status = REJECTED;
for (const func of this.rejectList) {
func(this.value);
}
}, 0);
}
try {
calllback(resolve, reject);
} catch (err) {
reject(err);
}
}
// 处理执行结果
then(onResolve, onReject) {
let promise = null;
if (this.status === PENDING) {
promise = new MyPromise((resolve, reject) => {
// 解决值穿透
onResolve = typeof onResolve === 'function' ? onResolve : (value) => value;
onReject = typeof onReject === 'function' ? onReject : (reason) => {throw reason};
this.resolveList.push(function(innerValue) {
try {
const value = onResolve(innerValue);
// resolve(value);
runThen(promise, value, resolve, reject);
} catch (err) {
reject(err);
}
});
this.rejectList.push(function(innerReason) {
try {
const value = onReject(innerReason);
// resolve(value);
runThen(promise, value, resolve, reject);
} catch (err) {
reject(err);
}
});
});
} else {
const innerValue = this.value;
const isFulfilled = this.status === STATUS.FULFILLED;
promise = new MyPromise((resolve, reject) => {
try {
const value = isFulfilled ? onResolve(innerValue) : onReject(innerValue); // 失败状态调用 onReject
// resolve(value);
runThen(promise, value, resolve, reject);
} catch (error) {
reject(error)
}
})
}
return promise;
// 运行promise,处理then返回新promise和循环引用问题
function runThen(promise, value, resolve, reject) {
if (promise === value) {
reject(new TypeError('Chaining cycle detected for promise'));
return;
}
if (value instanceof MyPromise) {
value.then((val) => runThen(promise, val, resolve, reject), (reason) => reject(reason));
} else {
resolve(value);
}
}
}
// 处理失败
catch(onReject) {
return this.then(null, onReject);
}
}
其他方法实现(finally、resolve、reject、all、race、any、allSettled、try)
// 私有变量,三个状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
/**
* 自己实现Promise
*/
class MyPromise {
constructor(calllback) {
// 状态
this.status = PENDING;
// 值
this.value = undefined;
// 成功回调列表
this.resolveList = [];
// 失败回调列表
this.rejectList = [];
const resolve = (value) => {
// 状态仅允许修改一次
if (this.status !== PENDING){
return;
}
setTimeout(() => {
this.value = value;
this.status = FULFILLED;
for (const func of this.resolveList) {
func(this.value);
}
}, 0);
}
const reject = (reason) => {
// 状态仅允许修改一次
if (this.status !== PENDING){
return;
}
setTimeout(() => {
this.value = reason;
this.status = REJECTED;
for (const func of this.rejectList) {
func(this.value);
}
}, 0);
}
try {
calllback(resolve, reject);
} catch (err) {
reject(err);
}
}
// 处理执行结果
then(onResolve, onReject) {
let promise = null;
if (this.status === PENDING) {
promise = new MyPromise((resolve, reject) => {
// 解决值穿透
onResolve = typeof onResolve === 'function' ? onResolve : (value) => value;
onReject = typeof onReject === 'function' ? onReject : (reason) => {throw reason};
this.resolveList.push(function(innerValue) {
try {
const value = onResolve(innerValue);
// resolve(value);
runThen(promise, value, resolve, reject);
} catch (err) {
reject(err);
}
});
this.rejectList.push(function(innerReason) {
try {
const value = onReject(innerReason);
// resolve(value);
runThen(promise, value, resolve, reject);
} catch (err) {
reject(err);
}
});
});
} else {
const innerValue = this.value;
const isFulfilled = this.status === STATUS.FULFILLED;
promise = new MyPromise((resolve, reject) => {
try {
const value = isFulfilled ? onResolve(innerValue) : onReject(innerValue); // 失败状态调用 onReject
// resolve(value);
runThen(promise, value, resolve, reject);
} catch (error) {
reject(error)
}
})
}
return promise;
// 运行promise,处理then返回新promise和循环引用问题
function runThen(promise, value, resolve, reject) {
if (promise === value) {
reject(new TypeError('Chaining cycle detected for promise'));
return;
}
if (value instanceof MyPromise) {
value.then((val) => runThen(promise, val, resolve, reject), (reason) => reject(reason));
} else {
resolve(value);
}
}
}
// 处理失败
catch(onReject) {
return this.then(null, onReject);
}
// 无论成功失败都执行
finally(callback) {
return this.then(callback, callback);
}
// 直接返回成功
static resolve(value) {
return new MyPromise((resolve, reject) => resolve(value));
}
// 直接返回失败
static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason));
}
// 所有都执行完毕
static all(promiseList) {
let count = 0;
const length = promiseList.length;
const valueList = [];
return new MyPromise((resolve, reject) => {
promiseList.forEach((promise, index) => {
promise.then((res) => {
valueList[index] = res;
count++;
if (count >= length) {
resolve(valueList);
}
}).catch((err) => {
reject(err);
});
});
});
}
// 第一个执行完毕
static race(promiseList) {
return new MyPromise((resolve, reject) => {
promiseList.forEach((promise, index) => {
promise.then((res) => {
resolve(res);
}).catch((err) => {
reject(err);
});
});
});
}
// 任何一个执行成功则返回成功,否则失败
static any(promiseList) {
let count = 0;
const length = promiseList.length;
const valueList = [];
return new MyPromise((resolve, reject) => {
promiseList.forEach((promise, index) => {
promise.then((res) => {
resolve(res);
}).catch((err) => {
valueList[index] = err;
count++;
if (count >= length) {
reject(valueList);
}
});
});
});
}
// 所有都执行完,无论成功失败都返回成功
static allSettled(promiseList) {
let count = 0;
const length = promiseList.length;
const valueList = [];
return new MyPromise((resolve, reject) => {
promiseList.forEach((promise, index) => {
promise.then((res) => {
valueList[index] = res;
count++;
if (count >= length) {
resolve(valueList);
}
}).catch((err) => {
valueList[index] = err;
count++;
if (count >= length) {
resolve(valueList);
}
});
});
});
}
// 执行同步或者异步函数
static try(func) {
return new MyPromise((resolve, reject) => {
const result = func();
resolve(result);
});
}
}