写点什么

手写实现 Promise

用户头像
GKNick
关注
发布于: 2020 年 07 月 21 日

Promise状态:Pending、Fullfilled、Rejected

  • Promise 对象的 then 方法会返回一个新的 Promise 对象

  • 后面的 then 方法就是在为上一个 then 返回的 Promise 注册回调

  • 前面 then 方法中回调函数的返回值会作为后面 then 方法回调的参数

  • 如果回调中返回的是 Promise,那后面 then 方法的回调会等待它的结束

源码实现:

// Promise 有三种状态:pending、fulfilled,rejected
const PENDING = "pending";
const FULFILLDED = "fulfilled";
const REJECTED = "rejected";
// Promise是个类
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
// promise初始化状态
status = PENDING;
// 成功后的值
value = undefined;
// 失败的原因
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
changeStatus(status, value) {
// 如果状态不是pending,则直接返回
if (this.status !== PENDING) return;
// 将状态变更为成功或者失败
this.status = status;
// 保存成功或者失败的值
this.value = value;
// 如果状态成功
if (status === FULFILLDED) {
while (this.successCallback.length) this.successCallback.shift()();
} else {
while (this.failCallback.length) this.failCallback.shift()();
}
}
resolve = (value) => {
this.changeStatus(FULFILLDED, value);
};
reject = (reason) => {
this.changeStatus(REJECTED, reason);
};
then(successCallback, failCallback) {
successCallback = successCallback ? successCallback : (value) => value;
failCallback = failCallback
? failCallback
: (reason) => {
throw reason;
};
let newPromise = new MyPromise((resolve, reject) => {
// 判断状态
if (this.status === FULFILLDED) {
// 通过设置setTimeout将下面代码变成异步代码达到避免获取不到newPromise对象问题
setTimeout(() => {
try {
const x = successCallback(this.value);
// 判断 x 的值是普通值还是Promise对象
// 如果是普通值 直接调用resolve
// 如果是Promise对象 查看Promise对象返回的结果
// 再根据Promise对象返回的结果 决定调用resolve 还是调用reject
promiseThen(newPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.status === REJECTED) {
// 通过设置setTimeout将下面代码变成异步代码达到避免获取不到newPromise对象问题
setTimeout(() => {
try {
const x = failCallback(this.reason);
// 判断 x 的值是普通值还是Promise对象
// 如果是普通值 直接调用resolve
// 如果是Promise对象 查看Promise对象返回的结果
// 再根据Promise对象返回的结果 决定调用resolve 还是调用reject
promiseThen(newPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else {
// 状态为pending
// 将成功回调和失败回调都存储起来
this.successCallback.push(() => {
setTimeout(() => {
try {
const x = successCallback(this.value);
// 判断 x 的值是普通值还是Promise对象
// 如果是普通值 直接调用resolve
// 如果是Promise对象 查看Promise对象返回的结果
// 再根据Promise对象返回的结果 决定调用resolve 还是调用reject
promiseThen(newPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.failCallback.push(() => {
setTimeout(() => {
try {
const x = failCallback(this.reason);
// 判断 x 的值是普通值还是Promise对象
// 如果是普通值 直接调用resolve
// 如果是Promise对象 查看Promise对象返回的结果
// 再根据Promise对象返回的结果 决定调用resolve 还是调用reject
promiseThen(newPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
// 返回Promise对象
return newPromise;
}
finally(callback) {
return this.then((value) => {
return MyPromise.resolve(callback()).then(() => value);
});
}
//
catch(callback) {
return this.then(undefined, callback);
}
static all(array) {
return new MyPromise((resolve, reject) => {
let result = [];
let count = 0;
function addData(index, value) {
result[key] = value;
count++;
if (count === array.length) {
resolve(result);
}
}
array.forEach((item, index) => {
if (item instanceof MyPromise) {
// Promise对象
item.then(
(value) => addData(index, value),
(reason) => reject(reason)
);
} else {
// 普通值
addData(index, item);
}
});
});
}
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise((resolve) => resolve(value));
}
static reject(reason) {
if (reason instanceof MyPromise) return reason;
return new MyPromise((_, reject) => reject(reason));
}
}
function promiseThen(promise, x, resolve, reject) {
if (promise === x) {
// 拒绝自我调用
reject(new TypeError("Chaining cycle detected for promise #<Promise>"));
}
if (x instanceof MyPromise) {
x.then(
(value) => resolve(value),
(reason) => reject(reason)
);
} else {
// 普通值
resolve(x);
}
}
module.exports = MyPromise;



用户头像

GKNick

关注

还未添加个人签名 2018.12.12 加入

还未添加个人简介

评论

发布
暂无评论
手写实现Promise