初識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對象有兩個特色:
基本用法:
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
參考上面例子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也是相同的道理。