promise A+ 規范簡述
- 一個promise必須有3個狀態,pending,fulfilled(resolved),rejected當處於pending狀態的時候,可以轉移到fulfilled(resolved)或者rejected狀態。當處於fulfilled(resolved)狀態或者rejected狀態的時候,就不可變。
- 一個promise必須有一個then方法,then方法接受兩個參數,resolve和reject
- 實現鏈式調用,then方法必須返回一個promise
promise A+ 源碼
Promise 源碼:https://github.com/then/promise/blob/master/src/core.js
一個簡單的實現
// this promise code refered to this blog
// http://www.cnblogs.com/liuzhenwei/p/5235473.html
var Promise = function (fn) {
var state = 'pending';
var doneList = [];
var failList= [];
this.then = function(done ,fail){
switch(state){
case 'pending':
doneList.push(done);
//每次如果沒有推入fail方法,我也會推入一個null來占位
failList.push(fail || null);
return this;
break;
case 'fulfilled':
done();
return this;
break;
case 'rejected':
fail();
return this;
break;
}
}
function tryToJson(obj) {
var value;
try {
value = JSON.parse(obj);
} catch (e) {
value = obj;
}
return value
}
function resolve(newValue){
state = 'fulfilled';
setTimeout(function(){
var value = tryToJson(newValue);
for (var i = 0; i < doneList.length; i++){
var temp = doneList[i](value);
if (temp instanceof Promise) {
var newP = temp;
for (i++; i < doneList.length; i++) {
newP.then(doneList[i], failList[i]);
}
} else {
value = temp;
}
}
}, 0);
}
function reject(newValue){
state = 'rejected';
setTimeout(function(){
var value = tryToJson(newValue);
var tempRe = failList[0](value);
//如果reject里面傳入了一個promise,那么執行完此次的fail之后,將剩余的done和fail傳入新的promise中
if(tempRe instanceof Promise){
var newP = tempRe;
for (i=1;i<doneList.length;i++) {
newP.then(doneList[i],failList[i]);
}
} else {
//如果不是promise,執行完當前的fail之后,繼續執行doneList
value = tempRe;
doneList.shift();
failList.shift();
resolve(value);
}
}, 0);
}
fn(resolve,reject);
}
其實是把then方法里的回調函數分別推入doneList和failList中,然后在promiFn執行完畢后開始調用 function resolve(newValue){} 里更改state狀態為fulfilled並且執行doneListi;
var promiFn = function (resolve, reject) {
setTimeout(function () {
resolve(1)
}, 0)
};
new Promise(promiFn)
.then(function (d) {
console.log(d)
}, function (e) {
console.log(e);
})
promise 鏈式調用
let bodyToJson = null;
request('http:www.baidu.com')
.then((d) => {
return otherPromise;
})
.then((d) => {
return anotherPromise
})
.then((d) => {
// ...
})
.catch((err) => {
// ...
});
還缺的 API
- Promise.all
- Promise.race
- Promise.prototype.catch
- Promise.prototype.finally
等待完善。
問題:為什么 promise 需要引入微任務
Promise 中的執行函數是同步進行的,但是里面存在着異步操作,在異步操作結束后會調用 resolve 方法,或者中途遇到錯誤調用 reject 方法,這兩者都是作為微任務進入到 EventLoop 中。但是你有沒有想過,Promise 為什么要引入微任務的方式來進行回調操作?
若 promise 回調放在進行宏任務隊列的隊尾,若隊列非常長,那么回調遲遲得不到執行,造成的效果就是應用卡頓。所以就引入了微任務。