es6 Promise的简单实现
程序员文章站
2022-06-30 19:13:12
...
需求分析
- Promise接受一个callback进行异步操作,callback接受两个方法参数resolve, reject
- then方法:
a. then方法接受一个callback方法
b. then以后可以继续调用then, 并将上次的then 的callback返回的值传递给下一个then的callback
c. then的执行需要发生在resolve之后 - catch方法,捕获异常处理:
a. reject方法需要调用
b. 其他地方
动手
1. 需求一, Promise的构造
function MyPromise(cb) {
cb(this.resolve.bind(this), this.reject.bind(this));
}
MyPromise.prototype.resolve = function(result) { ... }
MyPromise.prototype.reject = function(err) { ... }
2. 需求二, then的处理
2.1. 基于2a和2b的需求,可以解析为then传入的callback需要有地方存放,存放起来后等待构造函数的callbak执行后响应执行。
function MyPromise(cb) {
this.thenCallbacks = [];
cb(this.resolve.bind(this), this.reject.bind(this));
}
MyPromise.prototype.resolve = function(result) { ... }
MyPromise.prototype.reject = function(err) { ... }
MyPromise.prototype.then = function(cb) {
this.thenCallbacks.push(cb);
return this; // 返回自身以备多次调用
}
2.2. 需要提供方法来执行then的所有callback
function MyPromise(cb) {
this.result = null; // 临时存放resolve或者每次then callback后的结果
this.thenCallbacks = [];
cb(this.resolve.bind(this), this.reject.bind(this));
}
MyPromise.prototype.resolve = function(result) { ... }
MyPromise.prototype.reject = function(err) { ... }
MyPromise.prototype.then = function(cb) {
this.thenCallbacks.push(cb);
return this; // 返回自身以备多次调用
}
MyPromise.prototype.handleThen = function) {
this.thenCallbacks.forEach((cb) => {
this.result = cb(result);
})
return this.result; // 将最后结果返回
}
2.3. 在resolve以后调用handleThen, 并且确保handleThen执行在所有then调用之后
function MyPromise(cb) {
this.result = null; // 临时存放resolve或者每次then callback后的结果
this.thenCallbacks = [];
cb(this.resolve.bind(this), this.reject.bind(this));
}
MyPromise.prototype.resolve = function(result) {
this.result = result;
setTimeout(() => this.handleThen(), 0); // 放入调用栈底
}
MyPromise.prototype.reject = function(err) { ... }
MyPromise.prototype.handleThen = function() {
this.thenCallbacks.forEach((cb) => {
this.result = cb(result); // 每次将cb的返回值存起来,以备下一次调用
})
return this.result; // 将最后结果返回
}
3. 需求三,catch的处理
3.1 由于catch是一次性的,只需在调用的时候先存起来, 以及后面的执行方法
...
MyPromise.prototype.catch = function(cb) {
this.catchCallback = cb;
}
MyPromise.prototype.handleCatch = function(err) {
this.catchCallback && this.catchCallback(err);
}
3.2 需要处理Promise的reject方法
...
MyPromise.prototype.reject = function(err) {
setTimeout(() => this.handleCatch(err), 0); // 确保最后调用
}
...
3.3 还需要处理Promise回掉过程中产生的错误
function MyPromise(cb) {
this.result = null; // 临时存放resolve或者每次then callback后的结果
this.thenCallbacks = [];
this.catchCallback = null;
try {
cb(this.resolve.bind(this), this.reject.bind(this));
} catch(err) {
this.handleError(err);
}
}
...
3.4 还有then过程中的错误
...
MyPromise.prototype.handleThen = function() {
try {
this.thenCallbacks.forEach((cb) => {
this.result = cb(result); // 每次将cb的返回值存起来,以备下一次调用
})
} catch(err) {
setTimeout(() => this.catchCallback(err), 0); // 确保最后调用
}
return this.result; // 将最后结果返回
}
...
至此,基本功能已经实现,完整代码:
function MyPromise(cb) {
this.result = null; // 临时存放resolve或者每次then callback后的结果
this.thenCallbacks = [];
this.catchCallback = null;
try {
cb(this.resolve.bind(this), this.reject.bind(this));
} catch(err) {
this.handleError(err);
}
}
MyPromise.prototype.resolve = function(result) {
this.result = result;
setTimeout(() => this.handleThen(), 0); // 放入调用栈底
}
MyPromise.prototype.reject = function(err) {
setTimeout(() => this.handleCatch(err), 0); // 确保最后调用
}
MyPromise.prototype.then = function(cb) {
this.thenCallbacks.push(cb);
return this; // 返回自身以备多次调用
}
MyPromise.prototype.catch = function(cb) {
this.catchCallback = cb;
}
MyPromise.prototype.handleThen = function() {
try {
this.thenCallbacks.forEach((cb) => {
this.result = cb(result); // 每次将cb的返回值存起来,以备下一次调用
})
} catch(err) {
setTimeout(() => this.catchCallback(err), 0); // 确保最后调用
}
return this.result; // 将最后结果返回
}
MyPromise.prototype.handleCatch = function(err) {
this.catchCallback && this.catchCallback(err);
}
最后测试以下
new MyPromise((resolve, reject) => {
setTimout(() => resolve(3), 1000);
})
.then((result) => {
result += result
console.log('first call', result)
return reulst
})
.then((result) => {
result *= result
console.log('second call', result)
return reulst
})
.catch((err) => console.log(err))
// 结果
// 1s delay
// first call 6
// second call 36
上一篇: JS拖拽事件