Promise简易版实现
/**
* Readme:
* EasyPromise
* 本文实现了简易版的Promise类,实现功能包括:
* EasyPromise.prototype.then()
* EasyPromise.prototype.catch()
* EasyPromise.prototype.finally()
* EasyPromise.all()
* EasyPromise.race()
* TODO: 其他Promise内置api
* 代码的最下方提供了测试EasyPromise的api的demo,可以直接复制代码到本地.js,通过html引入即可直接运行
* 本实现 基于本人比较粗浅的理解,只实现了基本脉络,具体细节可能不是很严谨,仅供参考
*/
class EasyPromise {
static resolveCbStatic = undefined; // 供EasyPromise.all等静态方法使用
static rejectCbStatic = undefined; // 供EasyPromise.all等静态方法使用
resolveCb = undefined; // status == resolved 的回调
rejectCb = undefined; // status == reject 的回调
finallyCb = undefined; // status == resolved || status == reject 的回调,此方法无入参,
// 不依赖于 Promise 的执行结果
resolveData = undefined; // status == resolved 数据存储
rejectData = undefined; // status == reject 数据存储
status = 'pending'; // 记录Promise传入的异步任务状态
constructor (fn) {
if (!fn || typeof fn != 'function') {
console.log('EasyPromise方法传参无效')
return false;
}
this._resolve = this._resolve.bind(this)
this._reject = this._reject.bind(this)
this.then = this.then.bind(this)
this.catch = this.catch.bind(this)
this.finally = this.finally.bind(this)
fn(this._resolve, this._reject)
}
_resolve (data) {
if (this.status == 'pending') {
this.status = 'resolved';
this.resolveData = data;
this.resolveCb && this.resolveCb(data)
this.finallyCb && this.finallyCb()
}
}
_reject (err) {
if (this.status == 'pending') {
this.status = 'rejected';
this.rejectData = err;
this.rejectCb && this.rejectCb(data)
this.finallyCb && this.finallyCb()
}
}
then (fn) {
if (!fn || typeof fn != 'function') {
console.log('then方法传参无效')
return false;
}
// 链式编程(关键代码)
return new EasyPromise((resolve, reject) => {
this.resolveCb = () => {
let ret = fn(this.resolveData);
if (ret && ret.constructor == EasyPromise) {
ret.then((data) => {
resolve(data)
})
} else {
resolve(ret)
}
};
if (this.status == 'resolved') {
this.resolveCb(this.resolveData)
}
})
}
catch (fn) {
if (!fn || typeof fn != 'function') {
console.log('catch方法传参无效')
return false;
}
this.rejectCb = fn;
if (this.status == 'rejected') {
this.resolveCb(this.rejectData)
}
return this; // 链式编程
}
finally (fn) {
if (!fn || typeof fn != 'function') {
console.log('finally方法传参无效')
return false;
}
this.finallyCb = fn;
if (this.status == 'resolved' || this.status == 'rejected') {
this.finallyCb()
}
}
// 传入多个promise实例,当所有实例都执行结束后,返回结果的数组。如果任一实例catch,则all方法停止
static all (promiseList) {
if (!promiseList || Object.prototype.toString.call([]) != '[object Array]') {
console.log('all方法传参无效')
return false;
}
let len = promiseList.length;
let count = 0;
let res = [];
let catchFlag = false;
let invalid = false;
promiseList.forEach((item) => {
if (!item || item.constructor != EasyPromise) {
invalid = true;
}
})
if (invalid) {
console.log('promiseList 内包含不是EasyPromise的实例')
return false;
}
promiseList.forEach((item, index) => {
if (catchFlag) {
return false;
}
item.then((data) => {
count += 1;
res[index] = data;
if (len == count) { // 所有任务处理成功
this.resolveCbStatic(res)
}
}).catch(() => { // 任一任务出现错误
catchFlag = true;
this.rejectCbStatic(`all 方法调用错误, 对应索引-${index}`)
})
})
return this;
}
// 供all,race等静态方法使用
static then (fn) {
if (!fn || typeof fn != 'function') {
console.log('then方法传参无效')
return false;
}
this.resolveCbStatic = fn;
return this;
}
// 供all,race等静态方法使用
static catch (fn) {
if (!fn || typeof fn != 'function') {
console.log('catch方法传参无效')
return false;
}
this.rejectCbStatic = fn;
}
// 传入多个promise实例,返回最快执行结束的那个
static race (promiseList) {
if (!promiseList || Object.prototype.toString.call([]) != '[object Array]') {
console.log('all方法传参无效')
return false;
}
let invalid = false;
let status;
promiseList.forEach((item) => {
if (!item || item.constructor != EasyPromise) {
invalid = true;
}
})
if (invalid) {
console.log('promiseList 内包含不是EasyPromise的实例')
return false;
}
promiseList.forEach((item, index) => {
item.then((data) => {
if (status == 'end') {
return false;
}
status = 'end';
this.resolveCbStatic(data)
}).catch((err) => {
this.rejectCbStatic(`race 方法调用错误`)
})
})
return this;
}
}
/**
* 测试EasyPromise基础功能 打开注释即可
*/
// new EasyPromise((resolve, reject) => {
// let data = { value: '我是异步响应的数据' }
// setTimeout(function () {
// let flag = true;
// if (flag) {
// resolve(data)
// } else {
// reject('异步处理异常')
// }
// }, 1000)
// })
// .then((data) => {
// console.log(`响应数据为:`, data)
// return '哈哈哈'
// })
// .then((data) => {
// console.log(data, '第二个then的数据')
// return new EasyPromise((resolve, reject) => {
// setTimeout(function () {
// resolve('呵呵呵')
// }, 1000)
// })
// })
// .then((data) => {
// console.log(data, '第三个then的数据')
// })
// .catch((err) => {
// console.log(`发生错误:${err}`)
// })
// .finally((data) => {
// console.log(`我是finally触发`)
// })
/**
* 测试 EasyPromise.all 方法 打开注释即可
*/
// let promise1 = new EasyPromise((resolve, reject) => {
// setTimeout(function () {
// resolve('呵呵呵')
// }, 2000)
// })
// let promise2 = new EasyPromise((resolve, reject) => {
// setTimeout(function () {
// resolve('哈哈哈')
// }, 1000)
// })
// EasyPromise.all([ promise1, promise2 ])
// .then((data) => {
// console.log(data)
// })
// .catch((err) => {
// console.log(err)
// })
/**
* 测试 EasyPromise.race 方法 打开注释即可
*/
// let promise3 = new EasyPromise((resolve, reject) => {
// setTimeout(function () {
// resolve('呵呵呵')
// }, 2000)
// })
// let promise4 = new EasyPromise((resolve, reject) => {
// setTimeout(function () {
// resolve('哈哈哈')
// }, 1000)
// })
// EasyPromise.race([ promise3, promise4 ])
// .then((data) => {
// console.log(data)
// })
// .catch((err) => {
// console.log(err)
// })

浙公网安备 33010602011771号