基础内容
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)
基础功能实现
promise是一个对象
class MyPromise {
}
promise会接收一个执行器函数,这个函数会自动接收两个参数,一个resolve,一个rejected,他们分别代表异步操作成功执行和失败
class MyPromise {
constructor(executor) {
executor(this.resolve, this.rejected);
}
resolve = () => {
}
rejected = () => {
}
}
promise有三种状态,状态在resolve以及rejected时发生改变,状态发生改变后executor就不会再往下执行
class MyPromise {
status = 'pending'; // 新增
constructor(executor) {
executor(this.resolve, this.rejected);
}
resolve = () => {
if (this.status !== 'pending') return; // 新增
this.status = 'fulfilled'; // 新增
}
rejected = () => {
if (this.status !== 'pending') return; // 新增
this.status = 'rejected'; // 新增
}
}
promise有then方法,接收一个成功回调函数和一个失败回调函数作为参数,回调函数会在promise对象状态发生改变之后执行,回调函数会接收promise对象resolve或者rejected时传入的参数
class MyPromise {
status = 'pending';
constructor(executor) {
executor(this.resolve, this.rejected);
}
resolve = (result) => { // 修改
if (this.status !== 'pending') return;
this.status = 'fulfilled';
this.successResult = result; // 新增
}
rejected = (reason) => { // 修改
if (this.status !== 'pending') return;
this.status = 'rejected';
this.failReason = reason; // 新增
}
// 新增then方法
then = (successCallback, failCallback) => {
if (this.status === 'fulfilled') {
successCallback(this.successResult);
} else if (this.status === 'rejected') {
failCallback(this.failReason);
}
}
}
promise的基础功能看似完成了,但是如果我们这时候直接进行测试的话是有问题的
const testRequest = new MyPromise((resolve, rejected) => {
setTimeout(() => {
resolve('异步测试内容')
}, 1000);
})
testRequest.then((res) => {
console.log(res);
})
console.log('同步输出的内容')
//输出:同步输出的内容
异步内容没有输出。
这是因为 JavaScript 由上至下执行的时候,遇到 testRequest.then 的时候就直接执行了,而这时候 testRequest对象还没有 resolve,状态就还没发生变化,因此此时 this.status 是 pending,既不是 fulfilled, 也不是 rejected,回调函数也就不会执行。所以要考虑让对象能够在状态发生改变后执行回调函数,也就是要在 resolve和 rejected 方法内执行回调
调整:
class MyPromise {
status = 'pending';
constructor(executor) {
executor(this.resolve, this.rejected);
}
resolve = (result) => {
if (this.status !== 'pending') return;
this.status = 'fulfilled';
this.successResult = result;
// 新增
if (this.successCallback) {
this.successCallback(this.successResult);
}
}
rejected = (reason) => {
if (this.status !== 'pending') return;
this.status = 'rejected';
this.failReason = reason;
// 新增
if (this.failCallback) {
this.failCallback(this.failReason);
}
}
then = (successCallback, failCallback) => {
if (this.status === 'fulfilled') {
successCallback(this.successResult);
} else if (this.status === 'rejected') {
failCallback(this.failReason);
} else {
// 新增
this.successCallback = successCallback;
this.failCallback = failCallback;
}
}
}
再次进行测试:
const testRequest = new MyPromise((resolve, rejected) => {
setTimeout(() => {
resolve('测试内容')
}, 1000);
})
testRequest.then((res) => {
console.log(res);
})
console.log('同步输出的内容')
// 输出:
同步输出的内容
测试内容
promise的链式调用
其他内容就不写了,这里再写一下链式调用
new Promise(···).then(···).then(···).then(···)
在我们使用 Promise 时,当then中依旧返回了一个 Promise 对象时,就可以继续在后方调用 then 方法。回到我们自己写的 promise 中,要在 then 后面继续调用 then ,别的暂且不说,至少需要 then 方法中返回一个 Promise 对象,因此:
then = (successCallback, failCallback) => {
const chainPromise = new MyPromise((resolve, rejected) => { // 新增
if (this.status === 'fulfilled') {
successCallback(this.successResult);
} else if (this.status === 'rejected') {
failCallback(this.failReason);
} else {
this.successCallback = successCallback;
this.failCallback = failCallback;
}
})
return chainPromise; // 新增
}
promise 的 then 方法中又返回了一个 promise ,可能有点绕,这时我们只需要注意几点
首先明确 MyPromise 的特性:
- promise的执行器在对象创建时就会立即执行
new MyPromise 创建时带入的函数会立即执行
- 有三个状态,只有在 resolve 和 rejected 时状态才会发生改变,只有状态发生改变了,才会去执行回调函数
不调用 resolve,rejected的话,then 就不会执行
然后明确:
- 回调函数执行后可能依旧返回一个 Promise 对象
successCallback执行后可能会得到一个Promise对象
- 除了第一个 then,后续的 then 都是返回的单独声明的 chainPromise 的方法
也就是说和我们在链式调用中的 then 中返回的promise没有直接的关系,是两个promise
首先,因为 promise 的执行器在对象创建时就会立即执行,因此可以得知我们这样改写对我们原来的功能并不会有影响(加不加promise,原来基础功能部分的那些内容都会立即执行)
然后,不执行 resolve,rejected 的话回调就不会执行,也就是除了第一个 then 以外的 then 都不会执行(因为 chainPromise 内没有执行 resolve 或 rejected ),因此我们需要寻找执行新的 promise 对象的 resolve 和 rejected 的时机
继续,successCallback执行后可能会得到一个Promise对象,那么我们肯定要接收并且进行判断的
class MyPromise {
status = 'pending';
constructor(executor) {
executor(this.resolve, this.rejected);
}
resolve = (result) => {
if (this.status !== 'pending') return;
this.status = 'fulfilled';
this.successResult = result;
if (this.successCallback) {
// 修改
const result = this.successCallback(this.successResult);
// 新增
if (result instanceof MyPromise) {
} else {
}
}
}
rejected = (reason) => {
if (this.status !== 'pending') return;
this.status = 'rejected';
this.failReason = reason;
if (this.failCallback) {
this.failCallback(this.failReason);
}
}
then = (successCallback, failCallback) => {
const chainPromise = new MyPromise((resolve, rejected) => {
if (this.status === 'fulfilled') {
// 修改
const result = successCallback(this.successResult);
// 新增
if (result instanceof MyPromise) {
} else {
}
} else if (this.status === 'rejected') {
failCallback(this.failReason);
} else {
this.successCallback = successCallback;
this.failCallback = failCallback;
}
})
return chainPromise;
}
}
然后就简单了,执行 resolve 就行了,如果 result 是一个 promise 对象,我们就调用它的 then ,然后我们用 chainPromise 的 resovle 去接收一下就行了(上面说到的第二点,因为后续的 then 都是 chainPromise 的,不是 successCallback 返回的,因此必须用 chainPromise 的 resolve 去接收一下)
class MyPromise {
status = 'pending';
constructor(executor) {
executor(this.resolve, this.rejected);
}
resolve = (result) => {
if (this.status !== 'pending') return;
this.status = 'fulfilled';
this.successResult = result;
if (this.successCallback) {
const result = this.successCallback(this.successResult);
if (result instanceof MyPromise) {
result.then(res => this.chainResolve(res)); // 新增
} else {
this.chainResolve(result); // 新增
}
}
}
rejected = (reason) => {
if (this.status !== 'pending') return;
this.status = 'rejected';
this.failReason = reason;
if (this.failCallback) {
this.failCallback(this.failReason);
}
}
then = (successCallback, failCallback) => {
const chainPromise = new MyPromise((resolve, rejected) => {
// 上面的resolve函数肯定不能直接拿到这里的resolve,用两个参数接一下
this.chainResolve = resolve; // 新增
this.chainRejected = rejected; // 新增
if (this.status === 'fulfilled') {
const result = successCallback(this.successResult);
if (result instanceof MyPromise) {
result.then(res => resolve(res)); // 新增
} else {
resolve(result); // 新增
}
} else if (this.status === 'rejected') {
failCallback(this.failReason);
} else {
this.successCallback = successCallback;
this.failCallback = failCallback;
}
})
return chainPromise;
}
}
这里只写了 resolve 的内容,rejected同理
测试:
const testRequest = new MyPromise((resolve, rejected) => {
setTimeout(() => {
resolve('测试内容 1');
}, 1000);
})
testRequest.then((res) => {
console.log(res);
return new MyPromise((resolve, rejected) => {
setTimeout(() => {
resolve('测试内容 2');
}, 500);
})
}).then(res => {
console.log(res);
return new MyPromise((resolve, rejected) => {
setTimeout(() => {
resolve('测试内容 3');
}, 300);
})
}).then(res => {
console.log(res);
})
// 输出:
测试内容 1
测试内容 2
测试内容 3
收工,最后祝大家1024快乐,╰(°▽°)╯
加班不是福报,摸鱼才是王道!