前言
js执行单线程,而前端异步的实现实则为一个循环回调; Eventloop中异步任务区分了宏任务(如:setTimeout、setInterval、script)和微任务(如:process.nextTick、Promise、MutationObserver)
promise的实现实际上有点类似于这种eventloop,其循环return自身,每个then产生一层的promise,每层有专属的status状态,_nextResolveQueue保存的调用下一层级resolve的执行函数,以此从第一层promise执行完成回调resolve到后面一层一层的resolve回调到结束
思路
- 定义promise时,new Promise(function(res, rej){res()}).then(function(data){return new Promise()}).then(()=>{})
- _status promise实例初始化时候为pending,当该实例执行到_resolve函数后状态变为fulling
- _value 当每一层执行_resolve时会接收上一层级传过来的return值
- _nextResolveQueue存放下一层级对.then第一个参数nextResolveHandle函数的包装函数, 绑定该层级的resolve执行后便会遍历对_nextResolveQueue所有函数的执行
- 构造Promise函数时会传参数handle函数,并且立即执行,在其中会传入resolve参数,resolve的执行便会执行由.then参数组成的包装函数
- 包装函数执行后分两种情况,一返回真实的值,则直接执行下一层级的resolve并传入刚返回的真实值 ;二返回新的Promise实例,此时实例调用.then在此处生成新的promise层级,并将下层级的resolve函数放入.then第一个参数即nextResolveHandle;
const isFunction = varible => typeof varible === 'function'
function MyPromise(handle) {
this._status = 'pending'
this._value = ''
this._error = ''
this._nextResolveQueue = []
this._nextRejectQueue = []
try {
handle(this._resolve.bind(this), this._reject.bind(this))
} catch(e) {
console.log(e);
}
}
MyPromise._catchCallback = null;
MyPromise.prototype.then = function(nextResolveHandle, nextRejectHandle) {
let { _value, _error, _status, _nextResolveQueue, _nextRejectQueue } = this
return new MyPromise(function(nextResolve, nextReject) {
const resolveFn = function(value) {
try {
if(!isFunction(nextResolveHandle)) {
nextResolve(value)
} else {
let result = nextResolveHandle(value)
if(result instanceof MyPromise) {
result.then(nextResolve, nextReject)
} else {
nextResolve(result)
}
}
} catch(e) {
MyPromise._catchCallback && MyPromise._catchCallback(e)
}
}
const rejectFn = function(error) {
try {
if(!isFunction(nextRejectHandle)) {
nextReject(error)
} else {
let result = nextRejectHandle(error)
if(result instanceof MyPromise) {
result.then(nextResolve, nextReject)
} else {
nextReject(result)
}
}
} catch(e) {
MyPromise._catchCallback && MyPromise._catchCallback(e)
}
}
switch (_status) {
case 'pending':
// 待办等待resolve的执行,先存放待执行handle到queue中
_nextResolveQueue.push(resolveFn);
_nextRejectQueue.push(rejectFn);
break;
case 'fulling':
// 已经处理完,即没有等待直接resolve了
resolveFn(_value);
break;
case 'rejected':
// 还没执行完, 出现错误
rejectFn(_error)
break;
}
})
}
MyPromise.prototype.catch = function(handle) {
MyPromise._catchCallback = handle
}
MyPromise.prototype._resolve = function(data) {
let { _value, _status, _nextResolveQueue } = this
if(_status === 'fulling') return
const run = function() {
_status = 'fulling'
_value = data
let cb;
while(cb = _nextResolveQueue.shift()) {
cb(_value)
}
}
setTimeout(function(){
run()
})
}
MyPromise.prototype._reject = function(data) {
let { _error, _status, _nextRejectQueue } = this
if(_status === 'rejected') return
const run = function() {
_status = 'rejected'
_error = data
let cb;
while(cb = _nextRejectQueue.shift()) {
cb(_error)
}
}
setTimeout(function(){
run()
})
}