ES6只给出了Promise A+规范,实际上的Promise都是由各浏览器厂商实现的,我们今天自己写一个符合Promise A+规范的Promise
一、总览
二、基础版本
const PENDING = 'pending';
const FULFILED = 'fulfiled';
const REJECTED = 'rejected';
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILED;
this.value = value;
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfiled, onRejected) {
if (this.status === FULFILED) {
setTimeout(() => {
onFulfiled(this.value)
})
} else if (this.status === REJECTED) {
setTimeout(() => {
onRejected(this.reason)
})
}
}
catch(onRejected) {
return this.then(null, onRejected);
}
}
// 测试then
// 输出:1
const p = new Promise((resolve, reject) => {
reject(1);
}).then(data => {
console.log(data);
}, err => {
console.log(err);
})
// 测试catch
// 输出:1
const p = new Promise((resolve, reject) => {
reject(1);
}).catch(err => {
console.log(err)
})
三、链式调用
const PENDING = 'pending';
const FULFILED = 'fulfiled';
const REJECTED = 'rejected';
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILED;
this.value = value;
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfiled, onRejected) {
const self = this;
return new Promise((resolve, reject) => {
if (self.status === FULFILED) {
setTimeout(() => {
try {
onFulfiled(self.value)
} catch (e) {
reject(e);
}
})
} else if (self.status === REJECTED) {
setTimeout(() => {
try {
onRejected(self.reason);
} catch (e) {
reject(e);
}
})
}
})
}
catch(onRejected) {
return this.then(null, onRejected);
}
}
四、异步操作
const PENDING = 'pending';
const FULFILED = 'fulfiled';
const REJECTED = 'rejected';
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfiledCallBacks = [];
this.onRejectedCallBacks = [];
const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILED;
this.value = value;
this.onFulfiledCallBacks.forEach(fn => fn());
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.onRejectedCallBacks.forEach(fn => fn());
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfiled, onRejected) {
const self = this;
return new Promise((resolve, reject) => {
if (self.status === PENDING) {
setTimeout(() => {
try {
self.onFulfiledCallBacks.push(() => {
const res = onFulfiled(self.value);
res instanceof Promise ? res.then(resolve, reject) : resolve(res);
})
} catch (e) {
reject(e);
}
})
setTimeout(() => {
try {
self.onRejectedCallBacks.push(() => {
const res = onRejected(self.reason);
res instanceof Promise ? res.then(resolve, reject) : resolve(res);
})
} catch (e) {
reject(e);
}
})
} else if (self.status === FULFILED) {
setTimeout(() => {
try {
const res = onFulfiled(self.value);
res instanceof Promise ? res.then(resolve, reject) : resolve(res);
} catch (e) {
reject(e);
}
})
} else if (self.status === REJECTED) {
setTimeout(() => {
try {
const res = onRejected(self.reason);
res instanceof Promise ? res.then(resolve, reject) : resolve(res);
} catch (e) {
reject(e);
}
})
}
})
}
catch(onRejected) {
return this.then(null, onRejected);
}
}
// 测试
// 输出:
// Promise {
// status: 'fulfiled',
// value: 1000,
// reason: undefined,
// onFulfiledCallBacks: [],
// onRejectedCallBacks: []
// }
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
}, 1000);
}).then(data => {
return data*10;
}, err => {
return err*10;
}).then(data => {
return data*100;
}, err => {
return err*100;
})
setTimeout(() => {
console.log(p)
}, 2000);
五、值穿透
const PENDING = 'pending';
const FULFILED = 'fulfiled';
const REJECTED = 'rejected';
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfiledCallBacks = [];
this.onRejectedCallBacks = [];
const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILED;
this.value = value;
this.onFulfiledCallBacks.forEach(fn => fn());
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.onRejectedCallBacks.forEach(fn => fn());
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfiled, onRejected) {
onFulfiled = typeof onFulfiled === 'function' ? onFulfiled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => {
throw new Error(reason instanceof Error ? reason.message : reason);
}
const self = this;
return new Promise((resolve, reject) => {
if (self.status === PENDING) {
setTimeout(() => {
try {
self.onFulfiledCallBacks.push(() => {
const res = onFulfiled(self.value);
res instanceof Promise ? res.then(resolve, reject) : resolve(res);
})
} catch (e) {
reject(e);
}
})
setTimeout(() => {
try {
self.onRejectedCallBacks.push(() => {
const res = onRejected(self.reason);
res instanceof Promise ? res.then(resolve, reject) : resolve(res);
})
} catch (e) {
reject(e);
}
})
} else if (self.status === FULFILED) {
setTimeout(() => {
try {
const res = onFulfiled(self.value);
res instanceof Promise ? res.then(resolve, reject) : resolve(res);
} catch (e) {
reject(e);
}
})
} else if (self.status === REJECTED) {
setTimeout(() => {
try {
const res = onRejected(self.reason);
res instanceof Promise ? res.then(resolve, reject) : resolve(res);
} catch (e) {
reject(e);
}
})
}
})
}
catch(onRejected) {
return this.then(null, onRejected);
}
}
// 测试
// 输出:
// Promise {
// status: 'fulfiled',
// value: 1,
// reason: undefined,
// onFulfiledCallBacks: [],
// onRejectedCallBacks: []
// }
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
}, 1000);
}).then(222, 333);
setTimeout(() => {
console.log(p)
}, 2000);
六、静态方法
static resolve(value) {
if (value instanceof Promise) {
// 如果是Promise实例,直接返回
return value;
} else {
// 如果不是Promise实例,返回一个新的Promise对象,状态为FULFILLED
return new Promise((resolve, reject) => resolve(value));
}
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
})
}
static all(promiseArr) {
const len = promiseArr.length;
const values = new Array(len);
// 记录已经成功执行的promise个数
let count = 0;
return new Promise((resolve, reject) => {
for (let i = 0; i < len; i++) {
// Promise.resolve()处理,确保每一个都是promise实例
Promise.resolve(promiseArr[i]).then(
val => {
values[i] = val;
count++;
// 如果全部执行完,返回promise的状态就可以改变了
if (count === len) resolve(values);
},
err => reject(err),
);
}
})
}
static race(promiseArr) {
return new Promise((resolve, reject) => {
promiseArr.forEach(p => {
Promise.resolve(p).then(
val => resolve(val),
err => reject(err),
)
})
})
}
七、完整代码
const PENDING = 'pending';
const FULFILED = 'fulfiled';
const REJECTED = 'rejected';
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfiledCallBacks = [];
this.onRejectedCallBacks = [];
const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILED;
this.value = value;
this.onFulfiledCallBacks.forEach(fn => fn());
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.onRejectedCallBacks.forEach(fn => fn());
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfiled, onRejected) {
onFulfiled = typeof onFulfiled === 'function' ? onFulfiled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => {
throw new Error(reason instanceof Error ? reason.message : reason);
}
const self = this;
return new Promise((resolve, reject) => {
if (self.status === PENDING) {
setTimeout(() => {
try {
self.onFulfiledCallBacks.push(() => {
const res = onFulfiled(self.value);
res instanceof Promise ? res.then(resolve, reject) : resolve(res);
})
} catch (e) {
reject(e);
}
})
setTimeout(() => {
try {
self.onRejectedCallBacks.push(() => {
const res = onRejected(self.reason);
res instanceof Promise ? res.then(resolve, reject) : resolve(res);
})
} catch (e) {
reject(e);
}
})
} else if (self.status === FULFILED) {
setTimeout(() => {
try {
const res = onFulfiled(self.value);
res instanceof Promise ? res.then(resolve, reject) : resolve(res);
} catch (e) {
reject(e);
}
})
} else if (self.status === REJECTED) {
setTimeout(() => {
try {
const res = onRejected(self.reason);
res instanceof Promise ? res.then(resolve, reject) : resolve(res);
} catch (e) {
reject(e);
}
})
}
})
}
catch(onRejected) {
return this.then(null, onRejected);
}
static resolve(value) {
if (value instanceof Promise) {
// 如果是Promise实例,直接返回
return value;
} else {
// 如果不是Promise实例,返回一个新的Promise对象,状态为FULFILLED
return new Promise((resolve, reject) => resolve(value));
}
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
})
}
static all(promiseArr) {
const len = promiseArr.length;
const values = new Array(len);
// 记录已经成功执行的promise个数
let count = 0;
return new Promise((resolve, reject) => {
for (let i = 0; i < len; i++) {
// Promise.resolve()处理,确保每一个都是promise实例
Promise.resolve(promiseArr[i]).then(
val => {
values[i] = val;
count++;
// 如果全部执行完,返回promise的状态就可以改变了
if (count === len) resolve(values);
},
err => reject(err),
);
}
})
}
static race(promiseArr) {
return new Promise((resolve, reject) => {
promiseArr.forEach(p => {
Promise.resolve(p).then(
val => resolve(val),
err => reject(err),
)
})
})
}
}