Promise简介
Promise可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数(即回调地狱)。
Promise对象有构造函数executor,其含有两个参数resolve和reject,resolve来表示承诺实现,reject表示承诺拒绝。
Promise手写类测试工具
promises-aplus-tests 来测试你的promise是否符合promiseA+规范
使用方式
安装:npm i promises-aplus-tests -g
修改package.json:"test": "promises-aplus-tests MyPromise.js"
// MyPromise.js中新增代码
MyPromise.defer = MyPromise.deferred = function () {
let dfd = {};
dfd.promise = new MyPromise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
try {
module.exports = MyPromise;
} catch (err) { }
promise基本功能实现
下述示例代码中,定义了一个MyPromise类,定义三个常量状态(pending-未执行完成,fulfilled-承诺实现,rejected-承诺失败),构造函数中定义了promise的状态,成功值,失败值和成功的回调方法resolve、失败的回调reject方法,在MyPromise类的原型上定义了then方法。
该代码目前存在的缺陷,接下来我会从这两大方面进行完善示例代码:
1.在MyPromise中无法执行异步函数
2.无法进行链式和嵌套调用(会在下一篇文章中进行解释)
const promise = new MyPromise((resolve, reject) => {
resolve("promise fulfilled");
});
promise.then((value) => {
console.log("fulfilled:", value);
}, (reason) => {
console.log("rejected:", reason);
})
const FULFILLED_STATUS = "fulfilled";
const REJECTED_STATUS = "rejected";
const PENDING_STATUS = "pending";
class MyPromise {
constructor(executor) {
this.status = PENDING_STATUS;
this.value = undefined;
this.reason = undefined;
const resolve = (value) => {
if (this.status === PENDING_STATUS) {
this.status = FULFILLED_STATUS;
this.value = value;
}
}
const reject = (reason) => {
if (this.status === PENDING_STATUS) {
this.status = REJECTED_STATUS;
this.reason = reason;
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
if (this.status === FULFILLED_STATUS) {
onFulfilled(this.value);
} else if (this.status === REJECTED_STATUS) {
onRejected(this.reason);
}
}
}
promise功能完善
MyPromise中无法执行异步函数
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve("promise fulfilled");
}, 1000);
});
promise.then((value) => {
console.log("fulfilled:", value);
}, (reason) => {
console.log("rejected:", reason);
})
问题产生原因:setTimeout为异步函数,属于宏任务,延后执行。先调用promise.then方法,此时并未执行resolve,故promise的status状态仍为pending,在上述代码中并未对pengding的状态进行处理。
解决思路:依赖收集和派发更新。在then方法中对pending状态进行函数依赖收集,在resolve或reject方法被调用时进行函数调用。
const FULFILLED_STATUS = "fulfilled";
const REJECTED_STATUS = "rejected";
const PENDING_STATUS = "pending";
class MyPromise {
constructor(executor) {
this.status = PENDING_STATUS;
this.value = undefined;
this.reason = undefined;
this.onFulfillCallbacks = [];
this.onRejectCallbacks = [];
const resolve = (value) => {
if (this.status === PENDING_STATUS) {
this.status = FULFILLED_STATUS;
this.value = value;
this.onFulfillCallbacks.forEach(fn => fn());
}
}
const reject = (reason) => {
if (this.status === PENDING_STATUS) {
this.status = REJECTED_STATUS;
this.reason = reason;
this.onRejectCallbacks.forEach(fn => fn());
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
if (this.status === FULFILLED_STATUS) {
onFulfilled(this.value);
} else if (this.status === REJECTED_STATUS) {
onRejected(this.reason);
} else if (this.status === PENDING_STATUS) {
this.onFulfillCallbacks.push(() => {
onFulfilled(this.value);
})
this.onRejectCallbacks.push(() => {
onRejected(this.reason);
})
}
}
}