说起手写Promise 在我入行没多久的时候,其实就看了相关了源码的解析视频,那时候跟着视频一点点的写,毕竟看着视频写跟抄没什么区别 ,看完之后也是一知半解的感觉,但是那时候也没有很想深入的去了解它。从那以后就搁置了很久没有再看了。
今天再提起这个是为了复习一下以前的知识巩固一下,方便以后自己复习,废话不多说直接开干
那我就从 new Promise 开始
首先我们知道我们平常使用过程中都是通过new Promise去使用的,然后抛出一个Promise对象包含then方法并返回成功内容。
const p1 = new Promise((resolve, reject) => {
resolve(1)
});
p1.then((res) => {
console.log(res) // 1
})
那我们先来分析一下要实现这些要具备的条件
- promise有三种状态分别为:pending、fufilled、rejected,并且这三种状态是不可逆的
- 返回存在成功值和失败值
- 成功回调和错误回调
基于上面三点来实现一个初版Promise
/**
* 初始状态
*/
const PENDING = "PENDING";
/**
* 成功状态
*/
const FULFILLED = "FULFILLED";
/**
* 失败状态
*/
const REJECTED = "REJECTED";
class MyPromise {
constructor(executor) {
/**
* 状态
*/
this.state = PENDING;
/**
* 存放成功值
*/
this.value;
/**
* 存放失败值
*/
this.reason;
/**
* 成功回调
*/
let resolve = (value) => {
if (this.state === PENDING) {
this.value = value;
this.state = FULFILLED;
}
};
/**
* 失败回调
*/
let reject = (reason) => {
if (this.state === PENDING) {
this.reason = reason;
this.state = REJECTED;
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
if(this.state === FULFILLED) {
onFulfilled(this.value)
}
if(this.state === REJECTED) {
onRejected(thi.value)
}
}
}
现在去使用一下MyPromise看是否生效
const p2 = new MyPromise((resolve,reject) => {
resolve(2)
});
p2.then(res => {
console.log(res); // 2
})
我们看到控制台打印出了成功结果2 说明目前已经成功了一部分
但是如果我们这里使用了setTimeout的话就有问题,没有打印结果
const p2 = new MyPromise((resolve,reject) => {
setTimeout(() => {
resolve(2)
},0)
});
p2.then(res => {
})
这是什么原因呢因为我们刚才没有考虑异步的情况,当我们调用then的时候state还是pending状态,没有执行回调,那该如何处理呢,我们需要对异步情况进行处理
/**
* 初始状态
*/
const PENDING = "PENDING";
/**
* 成功状态
*/
const FULFILLED = "FULFILLED";
/**
* 失败状态
*/
const REJECTED = "REJECTED";
class MyPromise {
constructor(executor) {
/**
* 状态
*/
this.state = PENDING;
/**
* 存放成功值
*/
this.value;
/**
* 存放失败值
*/
this.reason;
/**
* 存放成功回调集合
*/
this.onFulfilledCallback = [];
/**
* 存放失败回调集合
*/
this.onRejectedCallback = [];
/**
* 成功回调
*/
let resolve = (value) => {
if (this.state === PENDING) {
this.value = value;
this.state = FULFILLED;
this.onFulfilledCallback.forEach((fn) => fn());
}
};
/**
* 失败回调
*/
let reject = (reason) => {
if (this.state === PENDING) {
this.reason = reason;
this.state = REJECTED;
this.onRejectedCallback.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
if(this.state === FULFILLED) {
onFulfilled(this.value)
}
if(this.state === REJECTED) {
onRejected(thi.reason)
}
if(thi.state === PENDING) {
this.onFulfilledCallback.push(() => {
onFulfilled(this.value)
})
this.onRejectedCallback.push(() => {
onRejected(this.reason)
})
}
}
}
通过判断state状态给成功和失败回到添加到回调里面,当调用resolve 或者 reject的时候 我们就可以对集合里面的事件进行统一处理, 从而处理异步的情况,到这里一个简版的Promise就实现完成了
完善Promise 实现链式调用
function resolvePromise(promise2, x, resolve, reject) {
let called; // 避免重复调用成功失败
// 判断循环引用
if (promise2 === x) {
return new TypeError("循环引用了");
}
// 判断数据类型
if ((typeof x === "object" && x !== null) || typeof c === "function") {
try {
let then = x.then; // 这里有可能then是用 defineProperity来定义的
if (typeof then === "function") {
// 暂且当做是 promise
then.call(
x,
(y) => {
if (called) {
return;
}
called = true;
resolvePromise(promise2, y, resolve, reject);
},
(n) => {
if (called) {
return;
}
called = true;
reject(n);
}
);
} else {
// 普通对象直接返回成功
resolve(x);
}
} catch (e) {
if (called) {
return;
}
called = true;
reject(e);
}
}
}
class MyPromise {
constructor(executor) {
/**
* 状态
*/
this.state = PENDING;
/**
* 存放成功值
*/
this.value;
/**
* 存放失败值
*/
this.reason;
/**
* 存放成功回调集合
*/
this.onFulfilledCallback = [];
/**
* 存放失败回调集合
*/
this.onRejectedCallback = [];
/**
* 成功回调
*/
let resolve = (value) => {
if (this.state === PENDING) {
this.value = value;
this.state = FULFILLED;
this.onFulfilledCallback.forEach((fn) => fn());
}
};
/**
* 失败回调
*/
let reject = (reason) => {
if (this.state === PENDING) {
this.reason = reason;
this.state = REJECTED;
this.onRejectedCallback.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
// onFulfilled onRejected 可能都为空v 可能为空 但是还是要继续传递下去 例如 then().then().then(data => data)
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (data) => data;
onRejected =
typeof onRejected === "function"
? onRejected
: (err) => {
throw err;
};
// 为了链式调用这里返回一个promise
let promise2 = new MyPromise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
// 对then方法里面的 返回值做处理
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
}
if (this.state === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
}
if (this.state === PENDING) {
this.onFulfilledCallback.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
});
this.onRejectedCallback.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
});
}
});
return promise2;
}
}
实现Promise.all方法
/**
* 返回全部成功的结果
*/
MyPromise.all = function (values) {
return new MyPromise((resolve, reject) => {
let arr = [];
/**
* 这里为何要使用index 而不是使用 arr.length呢
* 因为then 是异步的 当for循环结束了arr长度也就是valus长度
* 但是这个试试异步任务还未结束 resolve里面的值是空的
*/
let index = 0;
function processData(key, value) {
arr[key] = value;
++index;
if (index === values.length) {
resolve(arr);
}
}
for (let i = 0; i < values.length; i++) {
const current = values[i];
if (isPromise(current)) {
current.then((data) => {
processData(i, data);
}, reject);
} else {
processData(i, current);
}
}
});
};
实现Promise.resc方法
/**
* race 谁先成功或失败就返回谁
*/
MyPromise.race = function (values) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < values.length; i++) {
let current = values[i];
if (isPromise(current)) {
current.then(
(data) => {
resolve(data);
},
(err) => {
reject(err);
}
);
} else {
resolve(current);
}
}
});
};
实现Promise.resolve方法
/**
* Promise.resolve
*/
MyPromise.resolve = function (value) {
return new MyPromise((resolve, reject) => {
if (isPromise(value)) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
};
实现Promise.reject 方法
/**
* Promise.reject
*/
MyPromise.reject = function (reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
};
手写Promise github源码地址