实现Promise
class APromise {
static PENDING = 'pending';
static REJECTED = 'rejected';
static RESOLVED = 'resolved';
constructor(fun) {
this.PromiseState = APromise.PENDING;
this.PromiseResult = undefined;
this.resCbkList = [];
this.rejCbkList = [];
try {
fun(this.resolve.bind(this), this.reject.bind(this));
} catch (e) {
this.reject(e);
}
}
resolve(val) {
if (this.PromiseState === APromise.PENDING) {
this.PromiseState = APromise.RESOLVED;
this.PromiseResult = val;
this.resCbkList.forEach(fn=>{
fn()
})
}
}
reject(reason) {
if (this.PromiseState === APromise.PENDING) {
this.PromiseState = APromise.REJECTED;
this.PromiseResult = reason;
this.rejCbkList.forEach(fn=>{
fn()
})
}
}
then(resolveCbk, rejectCbk) {
const resCbk = typeof resolveCbk === 'function' ? resolveCbk : (val) => val;
const rejCbk =
typeof rejectCbk === 'function'
? rejectCbk
: (reason) => {
throw reason
};
const p2 = new APromise((resolve, reject) => {
if (this.PromiseState === APromise.RESOLVED) {
setTimeout(() => {
try {
const x = resCbk(this.PromiseResult);
resolvePromise(x, p2, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
}
if (this.PromiseState === APromise.REJECTED) {
setTimeout(() => {
try {
const x = rejCbk(this.PromiseResult);
resolvePromise(x, p2, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
}
if (this.PromiseState === APromise.PENDING) {
this.rejCbkList.push(() => {
setTimeout(() => {
try {
const x = rejCbk(this.PromiseResult);
resolvePromise(x, p2, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
});
this.resCbkList.push(() => {
setTimeout(() => {
try {
const x = resCbk(this.PromiseResult);
resolvePromise(x, p2, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
});
}
});
return p2;
}
}
function resolvePromise(x, p2, resolve, reject) {
if (x === p2) {
throw new TypeError('不能返回同一个promise');
}
if (x instanceof APromise) {
x.then((y) => {
resolvePromise(y, p2, resolve, reject);
}, reject);
} else if ((typeof x === 'object' || typeof x === 'function') && x !== null) {
let then;
try {
then = x.then;
} catch (err) {
return reject(err);
}
if (typeof then === 'function') {
let called = false;
try{
then.call(
x,
(y) => {
if (called) return;
called = true;
resolvePromise(y, p2, resolve, reject);
},
(reason) => {
if (called) return;
called = true;
reject(reason);
},
);
}catch(err) {
if (called) return;
called = true;
reject(err);
}
} else {
resolve(x);
}
} else {
resolve(x);
}
}
APromise.deferred = function () {
let result = {};
result.promise = new APromise((resolve, reject) => {
result.resolve = resolve;
result.reject = reject;
});
return result;
}
module.exports = APromise
如何检验实现的Promise是否符合规范
可以使用Promises/A+官方的测试工具 promises-aplus-tests 来对我们的myPromise进行测试。
如何使用promises-aplus-tests
1、先安装
npm install promises-aplus-tests -D
2、使用 CommonJS 对外暴露 myPromise 类并实现一个实现静态方法 deferred
// 以APromise为例
class APromise { ... }
function resolvePromise(x, p2, resolve, reject) {
APromise.deferred = function () {
let result = {};
result.promise = new APromise((resolve, reject) => {
result.resolve = resolve;
result.reject = reject;
});
return result;
}
module.exports = APromise
3、在package.json中加入如下命令
{
"scripts": { "test": "./myPromise.js" }
}
4、运行npm run start即可
5、可能遇到的问题
这是因为在package.json文件中将type值设为了module,当设置为“module”时,所在项目中(不包含node_modules)所有.js文件将被视为EsModule类型文件。所以我们上面用commonjs规范导出类就会出错
。将type属性移除即可,type属性默认为commonjs规范
参考文章
手把手一行一行代码教你“手写Promise“,完美通过 Promises/A+ 官方872个测试用例
[译]Promise/A+ 规范
Promise A+标准原文