Promise 詳解

一、Promise 的含義

初識Promise,要從多方面去理解,能夠直接百度Promise,只看別人博客的前面的含義介紹,先不深刻看別人的博客,基本能夠了解到:

  • promise原意:諾言; 許諾; 承諾;預示。
  • Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。連接描述
  • Promises 是一種 JavaScript 中處理異步代碼的方法,其實 Promises 已經存在多年,可是直到 ES2015 (ES6)才被標準化和引入,如今它們已經在 ES2017(ES8) 中被 async(異步) 函數所取代和擴展,可見發展之快。連接描述
  • 一個 Promise 就是一個對象,它表明了一個異步操做的最終完成或者失敗。連接描述
  • Promise對象用於異步操做,它表示一個還沒有完成且預計在將來完成的異步操做。
  • ES6 規定,Promise對象是一個構造函數,用來生成Promise實例。
  • Async functions(異步函數) 使用 promises API 做爲構建塊,所以理解 Promises 是必須的,即便在較新的代碼中,你可能會使用 async(異步) 函數而不是promises 。連接描述

二、同步、異步、回調函數相關概念

  • JavaScript的執行環境是單線程。所謂單線程,是指JS引擎中負責解釋和執行JavaScript代碼的線程只有一個,也就是一次只能完成一項任務,這個任務執行完後才能執行下一個,它會阻塞其餘任務。這個任務可稱爲主線程。但實際上還有其餘線程,如事件觸發線程、ajax請求線程等。
  • 同步模式,即上述所說的單線程模式,一次只能執行一個任務,函數調用後需等到函數執行結束,返回執行的結果,才能進行下一個任務。若是這個任務執行的時間較長,就會致使線程阻塞。
/* 例2.1 */
    var x = true;
    while(x);
    console.log("don't carry out");    //不會執行
    上面的例子即同步模式,其中的while是一個死循環,它會阻塞進程,所以第三句console不會執行。
    同步模式比較簡單,也較容易編寫。但問題也顯而易見,若是請求的時間較長,而阻塞了後面代碼的執行,
    體驗是很很差的。所以對於一些耗時的操做,異步模式則是更好的選擇。
  • 異步模式,即與同步模式相反,能夠一塊兒執行多個任務,函數調用後不會當即返回執行的結果,若是任務A須要等待,可先執行任務B,等到任務A結果返回後再繼續回調。最多見的異步模式就數定時器了,咱們來看看如下的例子。
/* 例2.2 */
    setTimeout(function() {
        console.log('taskA, asynchronous');
    }, 0);
    console.log('taskB, synchronize');
    //while(true);

    -------ouput-------
    taskB, synchronize
    taskA, asynchronous
    咱們能夠看到,定時器延時的時間明明爲0,但taskA仍是晚於taskB執行。
    這是爲何呢?因爲定時器是異步的,異步任務會在當前腳本的全部同步 任務執行完纔會執行。
    若是同步代碼中含有死循環,即將上例的註釋去掉,那麼這個異步任務就不會執行,由於同步任務阻塞了進程。
  • 回調函數,提起異步,就不得不談談回調函數了。上例中,setTimeout裏的function即是回調函數。能夠簡單理解爲:(執行完)回(來)調(用)的函數。
**WikiPedia對於callback的定義。**
    In computer programming, a callback is a piece of executable code that is passed as 
    an argument to other code, which is expected to call back (execute) the argument 
    at some convenient time.
    能夠看出,回調函數是一段可執行的代碼段,它以「參數」的形式傳遞給其餘代碼,
    在其合適的時間執行這段(回調函數)的代碼。
    **WikiPedia還定義**
    The invocation may be immediate as in a synchronous callback, 
    or it might happen at a later time as in an asynchronous callback.
    也就是說,回調函數不只能夠用於異步調用,通常同步的場景也能夠用回調。
    在同步調用下,回調函數通常是最後執行的。而異步調用下,可能一段時間後執行或不執行(未達到執行的條件)。

三、Promise 的特色和基本用法

promise對象有兩個特色:
  • 對象的狀態不受外界影響,pending(進行中)、fulfiled(已完成)、rejected(已失敗)
  • 一旦狀態改變,就不會再變,任什麼時候候均可以獲得這個結果,狀態改變只有兩種可能,稱爲(resolved)
基本用法:
es6規定,Promise對象是一個構造函數,用來生成Promise實例。
擴展構造函數回顧:特殊方法,建立對象時初始化對象,爲對象成員變量賦初始值,與new一塊兒使用。
一個類能夠有多個構造函數 ,可根據其參數個數的不一樣或參數類型的不一樣來區分它們 即構造函數的重載。
var promise = new promise(function(resove, reject){
  // ... some code
  if (/*異步成功*/){
    resove(value);
  } else{
    reject(error);。
  }
});
簡單例子1
例子用到了箭頭函數,寫法很容易理解,可參考另外一篇文章
let p= new Promise((resolve, reject)=>{
        let a1='成功傳出去的對象';
        let a2='失敗傳出去的對象';
        var timer = setTimeout(function () {
                     console.log('after resolve');
                    resolve(a1);
                    reject(a2);
                    console.log('after error');
                }, 1000);
    });
    p.then(value=>{
        console.log(value);
    },error=>{
        console.log('.then的第二個參數');
        console.log(error)
    });
    p.catch(error=>{
        console.log('.catch');
        console.log(error);
    });

上面例子的輸出效果,出現的第一行是Promise{<pending>},
而後再次輸入p 按回車執行打印出來p是這樣Promise{<resolved>}
而後點開看 能夠看到控制檯提示promiseStatus :resolved 說明promise的狀態已經成爲了resolved
圖片描述
上面例子把resolve(a1)去掉,結果以下:
圖片描述html

四、解讀promise中惟一的參數、resolve參數、reject參數、then()、catch()方法的意義

參考上面例子1

  • let p = new Promise(參數1),創造一個實例時,接受一個函數做爲參數1;
  • 參數1,做爲函數,也接受兩個參數分別是resolve和reject。它們是兩個函數,由 JavaScript 引擎提供,不用本身部署。注意:這兩個函數的做用就是改變Promise對象的狀態,一個是成功,一個是失敗,一旦調用了其中一個,狀態就不可改變和逆轉;
  • Promise實例生成之後,能夠用then方法分別指定resolved狀態和rejected狀態的回調函數,即便用p.then()來進一步的操做,注意:then()能夠接受兩個參數,這兩個參數也是函數,第一個表示成功的操做,就是調用了resolve(a1)後會進入,第二個表示失敗的操做,就是調用了reject(a1)後會進入,但第二個能夠省略;
  • p.catch和.then()第二個參數的效果是同樣,都會進入;
  • 例子1的resolve(a1)和reject(a2)同時存在時,只有在前面的有用,可註釋第一個看失敗的效果;
  • 例子中的resolve,reject只是個名字,其實能夠隨便改,不建議改;
  • 例子中p.then(value=>{console.log(value)},這裏面的value也只是個名字,其實能夠隨便改,不建議改;注意:value就是上面resolve(a1)中傳出來的a1,a1能夠是任何對象,a2也是相同的道理。
相關文章
相關標籤/搜索