实现一个promise之完成对x的处理并测试
function resolvePromise(promise2, x, resolve, reject) {
//如果promise和x是同一个对象,reject返回TypeError。
if(promise2 === x){
return reject(new TypeError('TypeError: Chaining cycle detected for promise #'));
};
//如果被调用多次,只执行第一次,或略其它调用,如果x不是方法,是不会出现多次调用的。
let called = false;
//如果x是对象或者方法
if((typeof x === 'object' && x !== null) || typeof x === 'function'){
//如果x是一个对象或者函数,取值then = x.then,如果x.then出错,抛出错误执行reject。
try{
let then = x.then;
//如果then是一个方法,用call改变this指向,把resolve和reject当作参数传递。
// 成功参数y,失败参数r,并调用成功失败函数。
if(typeof then === 'function'){
then.call(x, (y) => {
if(called) return;
called = true;
//如果return的是很多个promise,建议递归判断。
resolvePromise(promise2, y, resolve, reject);
}, (r) => {
if(called) return;
called = true;
reject(r);
})
}else{
//是对象,直接成功
resolve(x);
};
}catch (e) {
if(called) return;
called = true;
reject(e);
}
}else{
//普通值,直接返回成功
resolve(x);
}
};
完成之后,promise官方推荐了一个测试方法,只有通过测试才算符合标准的promise:
https://github.com/promises-aplus/promises-tests
全局安装promises-aplus-tests,然后写上下面的代码,最后执行promises-aplus-tests promise.js
全部通过就算完成了。
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = Promise;
附上完成的代码,可以跑看看:
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
//处理返回结果
function resolvePromise(promise2, x, resolve, reject) {
if(promise2 === x){
return reject(new TypeError('TypeError: Chaining cycle detected for promise #'));
};
let called = false;
if((typeof x === 'object' && x !== null) || typeof x === 'function'){
try{
let then = x.then;
if(typeof then === 'function'){
then.call(x, (y) => {
if(called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, (r) => {
if(called) return;
called = true;
reject(r);
})
}else{
resolve(x);
};
}catch (e) {
if(called) return;
called = true;
reject(e);
}
}else{
resolve(x);
}
};
class Promise {
constructor(executor){
this.state = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = (value) => {
if(this.state === PENDING){
this.state = FULFILLED;
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn());
}
};
let reject = (reason) => {
if(this.state === PENDING){
this.state = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try{
executor(resolve, reject);
}catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : y => y;
onRejected = typeof onRejected === 'function' ? onRejected : r => {throw r};
let promise2 = new Promise((resolve, reject) => {
if(this.state === FULFILLED){
setTimeout(() => {
try{
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject)
}catch (e) {
reject(e);
};
}, 0);
};
if(this.state === REJECTED){
setTimeout(() => {
try{
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject)
}catch (e) {
reject(e);
};
}, 0);
};
if(this.state === PENDING){
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try{
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject)
}catch (e) {
reject(e);
};
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try{
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject)
}catch (e) {
reject(e);
};
}, 0);
});
};
});
return promise2;
}
}
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = Promise;
image
发表评论 (审核通过后显示评论):