【JavaScript】实现类似promise的异步链式调用
2023/01/28 11:01:28
实现代码
class MyPromise {
constructor(fn) {
this.cbs = [];
const resolve = (value) => {
setTimeout(() => {
this.data = value;
this.cbs.forEach((cb) => cb());
});
};
fn(resolve);
}
then(onResolved) {
return new MyPromise((resolve) => {
const cb = () => {
const res = onResolved(this.data);
if (res instanceof MyPromise) {
res.then(resolve);
} else {
resolve(res);
}
};
this.cbs.push(cb);
});
}
}
实现思路
promise
的理念就是设置回调函数(then()
)并由使用者决定何时触发回调函数以及给回调函数传什么值(resolve()
)。
根据一个示例来理解内部实现:
new MyPromise((resolve) => {
setTimeout(() => {
resolve(1);
}, 500);
})
.then((res) => {
console.log(res);
return new MyPromise((resolve) => {
setTimeout(() => {
resolve(2);
}, 500);
});
})
.then(console.log);
构造函数的实现
class MyPromise {
constructor(fn) {
this.cbs = [];
const resolve = (value) => {
setTimeout(() => {
this.data = value;
this.cbs.forEach((cb) => cb());
});
};
fn(resolve);
}
// ...
}
这里重点在 resolve()
方法上,resolve()
方法接收一个值作为参数,这个值会被传递给 then(fn)
方法中的 fn
函数中。
resolve()
方法的最后开始执行 cbs
中的回调函数。
then(fn)
方法的实现
class MyPromise {
// ...
then(onResolved) {
// return 的值为 promiseNew
return new MyPromise((resolve) => {
const cb = () => {
const res = onResolved(this.data);
if (res instanceof MyPromise) {
// 此时 res 为 promiseCallback,将 promiseNew 的 resolve 方法注册为 promiseCallback 的回调
// 这样等到 promiseCallback 上的回调执行完毕后才会执行 promiseNew 上的回调,以实现异步链式调用
res.then(resolve);
} else {
resolve(res);
}
};
// this 为 promiseOld
this.cbs.push(cb);
});
}
}
then(fn)
方法中可能出现三个 MyPromise
实例,分别是:
- 调用
then(fn)
方法的MyPromise
实例,也就是当前的MyPromise
实例,记作 promiseOld。 then(fn)
方法将接收到的函数进行封装,返回一个新的MyPromise
实例,记作 promiseNew。then(fn)
方法接收的回调函数的返回值,也就是fn()
的返回值有可能是一个MyPromise
实例,记作 promiseCallback。
then(fn)
方法返回一个新的 MyPromise
实例 promiseNew,如果 fn()
的返回值也是 MyPromise
实例,那么 promiseNew 会等到 promiseCallback 的异步回调链执行完毕后再执行自己的 resolve()
方法。