我们已经很习惯用Promise了,但是它的实现原理是什么呢?下面我们来分析一下。
根据阮一峰老师的《ES6入门》中对于Promise的讲解。我们可以发现,Promise有两大特点:
根据我们使用Promise的情况,以及特点我们总结出来了以下几点:
1、Promise是一个异步操作。
2、Promise有三种状态(pending、fulfilled、rejected),初始为pending,其他两种为结果状态。
3、如果状态已经发生改变,那么再then的时候会立即返回结果。
4、Promise构造函数接受一个函数,函数有resolve、reject参数。
5、Promise通过then可以添加多个回调函数,当状态改变以后,会触发这些对应状态的回调的执行。
6、then有两个参数,一个代表成功的回调、一个失败的回调,结果状态的值会进入回调。
7、promise会catch住内部的异常情况。
通过以上总结,我们可以初步实现一个Promise的骨架。
const STATUS = Object.freeze({ // 定义三种状态
PENDING: "pending",
FULFILLED: "fulfilled",
REJECTED: "rejected"
})
class MyPromise {
_status = STATUS.PENDING; // 初始状态
_value = undefined; // 执行结果
_fulfilledFun = []; // fulfilled状态对应执行的任务队列
_rejectedFun = [] // rejected状态对应执行的任务队列
constructor(handle) {
if (!this._isFunction(handle)) {
throw TypeError('arguments must be a function')
}
try { // promise 会catch住内部的执行异常
handle(this._resolve.bind(this), this._reject.bind(this)) // Promise构造函数的回调有两个参数
} catch (err) {
this._reject(err)
}
}
_isFunction(handle) {
return typeof handle === 'function'
}
_run(tasks) {
let cb;
while (cb = tasks.shift()) {
cb()
}
}
_resolve(val) {
if (this._status !== STATUS.PENDING) return;
this._status = STATUS.FULFILLED;
this._value = val;
setTimeout(() => { /// 为了模拟异步,实现跟promise一样的异步效果,但是此处其实是宏队列,不是真正的promise微队列
this._run(this._fulfilledFun)
}, 0)
}
_reject(val) {
if (this._status !== STATUS.PENDING) return;
this._status = STATUS.REJECTED;
this._value = val;
setTimeout(() => {
this._run(this._rejectedFun)
}, 0)
}
then(resolve, reject) {
const { _status, _value } = this;
switch (_status) {
// 添加多个回调到对应状态任务队列
case STATUS.PENDING:
this._fulfilledFun.push(resolve)
this._rejectedFun.push(reject)
break;
//如果状态变化则立即返回结果
case STATUS.FULFILLED:
resolve(_value)
break;
case STATUS.REJECTED:
reject(_value)
break;
}
}
}
var p = new MyPromise((res, rej) => {
res(3333)
})
p.then((res) => {
console.log(1, res)
})
console.log(1)
// 执行结果
//1
//1 3333
复制代码
以上我们实现了一个基本的Promise骨架。
如图我们可以发现,then返回的是一个Promise实例,但是我们上一步并没有任何返回,所以我们要把then改造一下,对then进行一个扩充。
class MyPromise {
//.....
//用于对then的返回值进行处理
_handleCheck(preTask, nextTask, nextResolve, nextReject) {
let result = this._value;
try {
if (this._isFunction(preTask)) {
result = preTask(result)
if (result instanceof MyPromise) { // 如果then返回的是一个promise的话,那么下一个链式调用使用的是then中promise的返回值
result.then(nextResolve, nextReject)
} else {
nextTask(result)
}
} else { // 这一点需要注意,如果then不是一个函数的话,那么then的下一个链式调用采用的是then接受到的值
nextTask(result)
}
} catch (err) {
nextReject(err)
}
}
then(resolve, reject) {
const { _status } = this;
return new MyPromise((nextResolve, nextReject) => {
//进行队列的预处理,主要是then结果判断,为了保证正确的给链式调用的下一级传参
const _fulfilledHandle = this._handleCheck.bind(this, resolve, nextResolve, nextResolve, nextReject)
const _rejectedHandle = this._handleCheck.bind(this, reject, nextReject, nextResolve, nextReject)
switch (_status) {
case STATUS.PENDING:
this._fulfilledFun.push(_fulfilledHandle)
this._rejectedFun.push(_rejectedHandle)
break;
case STATUS.FULFILLED:
_fulfilledHandle()
break;
case STATUS.REJECTED:
_rejectedHandle()
break;
}
})
}
}
var p = new MyPromise((res, rej) => {
res(3333)
})
p.then((res) => {
console.log(1, res)
return 67
}).then((res) => {
console.log(5, res)
})
/**
* 返回结果
1
1 3333
5 67
*/
复制代码
这样一个基本核心的功能就已经实现了。Promise还有一些其他的方法,我们通过这些基础的功能就可以一一实现了。
1、catch
catch(reject) {
return this.then(undefined, reject)
}
复制代码
2、finally
finally(callback) {
return this.then(
value => MyPromise.resolve(callback()).then(() => value),
error => MyPromise.resolve(callback()).then(() => {throw error})
)
}
复制代码
3、all
static all(list) {
return new MyPromise((res, rej) => {
const values = [];
const size = list.length;
for(let [index, p] of list.entries() ){
MyPromise.resolve(p).then(v => {
values[index] = v;
if(index === size - 1) res(values)
}).catch(err => rej(err))
}
})
}
复制代码
4、race
static race(list) {
return new MyPromise((res, rej) => {
for(let p of list) {
// 使用MyPromise.resolve 而不是直接p.then 是为了防止p不是一个正常的promise
MyPromise.resolve(p).then(result => {
res(result)
}, error => rej(error))
}
})
}
复制代码
5、allSettled
static allSettled(list) {
const values = [];
const size = list.length;
let count = 0;
return new MyPromise((res, rej) => {
const getValues = (val, index) => {
values[index] = val;
count++;
if(count === size) res(values)
}
for(let [index, p] of list.entries()) {
MyPromise.resolve(p).then(result => {
getValues(result, index)
}, error => getValues(error, index))
}
})
}
复制代码
6、any
static any(list) {
const values = [];
const size = list.length;
return new MyPromise((res, rej) => {
for(let [index, p] of list.entries()) {
MyPromise.resolve(p).then(result => {
res(result)
}, error => {
values[index] = error;
if(index === size - 1) rej(values)
})
}
})
}
复制代码
以下是完整代码的实现。
const STATUS = Object.freeze({
PENDING: "pending",
FULFILLED: "fulfilled",
REJECTED: "rejected"
})
class MyPromise {
_status = STATUS.PENDING;
_value = undefined;
_fulfilledFun = [];
_rejectedFun = []
constructor(handle) {
if (!this._isFunction(handle)) {
throw TypeError('arguments must be a function')
}
try {
handle(this._resolve.bind(this), this._reject.bind(this))
} catch (err) {
this._reject(err)
}
}
_isFunction(handle) {
return typeof handle === 'function'
}
_run(tasks) {
let cb;
while (cb = tasks.shift()) {
cb()
}
}
_resolve(val) {
if (this._status !== STATUS.PENDING) return;
this._status = STATUS.FULFILLED;
this._value = val;
setTimeout(() => { /// 为了模拟异步,实现跟promise一样的异步效果,但是此处其实是宏队列,不是真正的promise微队列
this._run(this._fulfilledFun)
}, 0)
}
_reject(val) {
if (this._status !== STATUS.PENDING) return;
this._status = STATUS.REJECTED;
this._value = val;
setTimeout(() => {
this._run(this._rejectedFun)
}, 0)
}
_handleCheck(preTask, nextTask, nextResolve, nextReject) {
let result = this._value;
try {
if (this._isFunction(preTask)) {
result = preTask(result)
if (result instanceof MyPromise) {
result.then(nextResolve, nextReject)
} else {
nextTask(result)
}
} else {
nextTask(result)
}
} catch (err) {
nextReject(err)
}
}
then(resolve, reject) {
const { _status } = this;
return new MyPromise((nextResolve, nextReject) => {
const _fulfilledHandle = this._handleCheck.bind(this, resolve, nextResolve, nextResolve, nextReject)
const _rejectedHandle = this._handleCheck.bind(this, reject, nextReject, nextResolve, nextReject)
switch (_status) {
case STATUS.PENDING:
this._fulfilledFun.push(_fulfilledHandle)
this._rejectedFun.push(_rejectedHandle)
break;
case STATUS.FULFILLED:
_fulfilledHandle()
break;
case STATUS.REJECTED:
_rejectedHandle()
break;
}
})
}
catch(reject) {
return this.then(undefined, reject)
}
finally(callback) {
return this.then(
value => MyPromise.resolve(callback()).then(() => value),
error => MyPromise.resolve(callback()).then(() => {throw error})
)
}
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value))
}
static reject(value) {
if (value instanceof MyPromise) return value;
return new MyPromise((resolve, reject) => reject(value))
}
static all(list) {
return new MyPromise((res, rej) => {
const values = [];
const size = list.length;
for(let [index, p] of list.entries() ){
MyPromise.resolve(p).then(v => {
values[index] = v;
if(index === size - 1) res(values)
}).catch(err => rej(err))
}
})
}
static race(list) {
return new MyPromise((res, rej) => {
for(let p of list) {
// 使用MyPromise.resolve 而不是直接p.then 是为了防止p不是一个正常的promise
MyPromise.resolve(p).then(result => {
res(result)
}, error => rej(error))
}
})
}
static allSettled(list) {
const values = [];
const size = list.length;
let count = 0;
return new MyPromise((res, rej) => {
const getValues = (val, index) => {
values[index] = val;
count++;
if(count === size) res(values)
}
for(let [index, p] of list.entries()) {
MyPromise.resolve(p).then(result => {
getValues(result, index)
}, error => getValues(error, index))
}
})
}
static any(list) {
const values = [];
const size = list.length;
return new MyPromise((res, rej) => {
for(let [index, p] of list.entries()) {
MyPromise.resolve(p).then(result => {
res(result)
}, error => {
values[index] = error;
if(index === size - 1) rej(values)
})
}
})
}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END