不要被then需要異步執(zhí)行嚇到了擎椰,then傳入的是個函數(shù)膨桥,什么時候調(diào)用创葡,應(yīng)該由第一次回調(diào)決定
靜態(tài)的all浙踢、race等方法,后面再補充
function promise(func){
this.state = 'pending'; //狀態(tài)
this.resolveArg; //回調(diào)參數(shù)灿渴,下同
this.rejectArg;
this.thenQueue = []; //調(diào)用隊列
this.thenable = true;
this.resolveFunc = _resolveFunc.bind(this);
this.rejectFunc = _rejectFunc.bind(this);
this.catchFunc = _catchFunc.bind(this);
//將 res洛波,rej回調(diào)傳入作用域內(nèi)并執(zhí)行主函數(shù)
try {
func(this.resolveFunc,this.rejectFunc)
} catch (e) {
this.catchFunc(e);
}
}
promise.prototype = {
constructor : promise,//綁定構(gòu)造器
/* 調(diào)用then,只需要把傳入的回調(diào)壓進then隊列里即可骚露,不需要timeout操作*/
then : function(res,rej) {
if (!this.thenable) {
return this;
}
//
this.thenQueue.push({
res : res,
rej : rej
})
return this;
},
catch: function(func) {
this.catchFunc = func;
return this
},
finally: function (func) {
this.finallyFunc = func;
this.thenable = false;
return this;
}
}
/* rej蹬挤、res回調(diào)會將then隊列里的函數(shù)依次執(zhí)行,并且上一個then的返回值作為下一個then的參數(shù) */
function _rejectFunc (args) {
this.rejectArg = args;
this.state = 'rejected'
if(!this.thenQueue.length){return;}
while (this.thenQueue.length) {
rejCallback = this.thenQueue.shift().rej;
try {
var newReturns = rejCallback(this.rejectArg);
this.rejectArg = newReturns;
} catch (e) {
this.catchFunc(e)
}
}
this.finallyFunc && this.finallyFunc();
this.thenable = false;
}
function _resolveFunc (args) {
this.resolveArg = args;
this.state = 'fullfilled'
if(!this.thenQueue.length){return;}
while (this.thenQueue.length) {
resCallback = this.thenQueue.shift().res;
try {
var newReturns = resCallback(this.resolveArg)
this.resolveArg = newReturns;
} catch(e) {
this.catchFunc(e)
}
}
this.finallyFunc && this.finallyFunc();
this.thenable = false;
}
function _catchFunc (e){
throw Error('Uncaught promise error:' + e)
}
new promise(res=>{
setTimeout(()=>{
res([123])
},1000)
}).then(res=>{
console.log('res',res)
return 'bbb'
}).then(res=>{
console.log(res)
})
存在的問題
Promise.then是在下一個MicroTask調(diào)用的棘幸,而上述的代碼是同步執(zhí)行
new promise(res=>{
setTimeout(()=>{
res()
})
console.log('搶先一步')
}).then()
設(shè)置了setTimeout會使then在MacroTask之后調(diào)用
Node.js中可以使用setImmediate焰扳,就能使其真正的在下一個MicroTask執(zhí)行