ES6之Promise

什麼是Promise

Promise是JavaScript中爲解決異步問題,結合社區已有規範,提出的一種異步編程解決方案。 在ES6中,Promise自己一個構造函數,原型鏈上有then、catch和finally等方法。自身的靜態方法有all、race、reject和resolve等。javascript

Promise的三個狀態

請求態pending完成態fulfilled拒絕態rejectedjava

一個須要記住的點:git

Promise的狀態只能夠由 pending ——> fulfilledpending——> rejected,一旦Promise狀態發生改變,也就是說一旦Promise的狀態變爲fulfilled或者rejected,那麼它的轉態便不可再變。 [image:90230504-F905-4CDC-A4BE-A5FF2FE79F33-4052-0000191F58D20B47/52d29942398343318f015c5b334766a4.png] github

手寫一個Promise

(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)
}
)()
複製代碼

Promise的鏈式調用

回調地獄

使用回調解決異步編程的方案是一種比較簡單直接方式。編程

// 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

Promise跟async/await的關係

簡單地說,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
})()
複製代碼

async/await僅僅只是Promise的語法糖嗎

相對於Promise,在處理 then 的調用鏈時,async/await的寫法可以更清晰準確的寫出代碼 而且也能優雅地解決回調地獄問題。這更符合人類的線性思惟方式。

【翻譯】Promises/A+規範-圖靈社區 GitHub - tildeio/rsvp.js: A lightweight library that provides tools for organizing asynchronous code

相關文章
相關標籤/搜索