Promise是JavaScript中爲解決異步問題,結合社區已有規範,提出的一種異步編程解決方案。 在ES6中,Promise自己一個構造函數,原型鏈上有then、catch和finally等方法。自身的靜態方法有all、race、reject和resolve等。javascript
請求態pending、完成態fulfilled、拒絕態rejected。java
一個須要記住的點:git
Promise的狀態只能夠由
pending ——> fulfilled
或pending——> rejected
,一旦Promise狀態發生改變,也就是說一旦Promise的狀態變爲fulfilled或者rejected,那麼它的轉態便不可再變。 [image:90230504-F905-4CDC-A4BE-A5FF2FE79F33-4052-0000191F58D20B47/52d29942398343318f015c5b334766a4.png] github
(function() {
function P(fn) {
var self = this;
this.fullfilleds = [];
this.faileds = [];
function resolve() {
self.fullfilled = true;
let args = Array.prototype.slice.call(arguments);
self.result = args;
if (self.fullfilleds.length) {
// 執行then方法註冊的函數,真正的操做是將callbacks隊列中的回調一一執行
self.fullfilleds.forEach(fn=>{
fn.apply(null, args);
})
}
}
function reject() {}
fn.call(null, resolve, reject);
}
P.prototype.then = function(fullfilled, failed) {
if (this.fullfilled) {
fullfilled.apply(null, this.result)
} else if (this.failed) {
failed(this.failed);
} else {
this.fullfilleds.push(fullfilled);
this.faileds.push(failed);
}
}
const p = new P((resolve,reject)=>{
resolve('sync');
});
p.then(d=>{
console.log(d);
});
setTimeout(()=>{
p.then(d=>{
console.log(d + 2);
})
}, 2000)
}
)()
複製代碼
使用回調解決異步編程的方案是一種比較簡單直接方式。編程
// demo 1
setTimeout( ()=>{
console.log("1秒鐘後輸出");
}, 1000);
// demo 2
Ajax.get('xxx', {}, function(data){
// DO something
});
複製代碼
這種方案單層的回調還算能夠,但若是回調裏面又出現新的回調,產生嵌套。 像這種app
Ajax.get('xxx', {}, function(){
Ajax.get('xxx', {}, function(){
Ajax.get('xxx', {}, function(){
// do something
})
});
})
複製代碼
Promise的鏈式調用則不存在此問題,在能夠控制順序 的前提下,能夠比較直觀地編寫異步代碼。異步
在回調函數的方案中,因爲回調函數執行棧與原函數分開,致使沒法捕獲異常。這一點在Promise中,藉助rejected,能夠將錯誤捕獲。async
不一樣於回調函數,Promise藉助then方法能夠控制程序的執行。若是經過回調函數,調用者是不知道異步程序結束而後調用回調的。異步程序結束後,回回調函數被異步程序本身在後臺默默調用,調用者失去了程序的控制權。但Promise中的then方法不存在此問題,由於then方法的調用者仍是主程序自己。ide
簡單地說,async/await
是Promise的語法糖。由於async函數返回值是Promise類型,await 後面的語句吐出 的是一個Promise傳給then方法的數據。異步編程
(async function(){
async function f(){
return 1;
}
let a = f();
console.log( a instanceof Promise); // true
let b = await a;
console.log(b); // 1
let c = await Promise.resolve(2);
console.log(c); // 2
})()
複製代碼
相對於Promise,在處理 then 的調用鏈時,async/await的寫法可以更清晰準確的寫出代碼 而且也能優雅地解決回調地獄問題。這更符合人類的線性思惟方式。
【翻譯】Promises/A+規範-圖靈社區 GitHub - tildeio/rsvp.js: A lightweight library that provides tools for organizing asynchronous code