特點
- 對象的狀態不受外界影響 (3種狀態)
- Pending狀態(進行中)
- Fulfilled狀態(已成功)
- Rejected狀態(已失敗)
- 一旦狀態改變就不會再變 (兩種狀態改變:成功或失敗)
- Pending -> Fulfilled
- Pending -> Rejected
用法
創建Promise實例
var promise = new Promise(function(resolve, reject){ // ... some code if (/* 異步操作成功 */) { resolve(value); } else { reject(error); } })
Promise構造函數接受一個函數作為參數,該函數的兩個參數分別是resolve
和reject
。它們是兩個函數,由JavaScript引擎提供,不用自己部署。
resolve作用是將Promise對象狀態由“未完成”變為“成功”,也就是Pending -> Fulfilled
,在異步操作成功時調用,並將異步操作的結果作為參數傳遞出去;而reject函數則是將Promise對象狀態由“未完成”變為“失敗”,也就是Pending -> Rejected
,在異步操作失敗時調用,並將異步操作的結果作為參數傳遞出去。
then
Promise實例生成后,可用then
方法分別指定兩種狀態回調參數。then 方法可以接受兩個回調函數作為參數:
- Promise對象狀態改為Resolved時調用 (必選)
- Promise對象狀態改為Rejected時調用 (可選)
基本用法示例
function sleep(ms) { return new Promise(function(resolve, reject) { setTimeout(resolve, ms); }) } sleep(500).then( ()=> console.log("finished"));
這段代碼定義了一個函數sleep,調用后,等待了指定參數(500)毫秒后執行then中的函數。值得注意的是,Promise新建后就會立即執行。
執行順序
接下來我們探究一下它的執行順序,看以下代碼:
let promise = new Promise(function(resolve, reject){ console.log("AAA"); resolve() }); promise.then(() => console.log("BBB")); console.log("CCC") // AAA // CCC // BBB
執行后,我們發現輸出順序總是 AAA -> CCC -> BBB
。表明,在Promise新建后會立即執行,所以首先輸出 AAA
。然后,then方法指定的回調函數將在當前腳本所有同步任務執行完后才會執行,所以BBB 最后輸出
。
與定時器混用
首先看一個實例:
let promise = new Promise(function(resolve, reject){ console.log("1"); resolve(); }); setTimeout(()=>console.log("2"), 0); promise.then(() => console.log("3")); console.log("4"); // 1 // 4 // 3 // 2
可以看到,結果輸出順序總是:1 -> 4 -> 3 -> 2
。1與4的順序不必再說,而2與3先輸出Promise的then,而后輸出定時器任務。原因則是Promise屬於JavaScript引擎內部任務,而setTimeout則是瀏覽器API,而引擎內部任務優先級高於瀏覽器API任務,所以有此結果。
拓展 async/await
async
顧名思義,異步。async函數對 Generator 函數的改進,async 函數必定返回 Promise,我們把所有返回 Promise 的函數都可以認為是異步函數。特點體現在以下四點:
- 內置執行器
- 更好的語義
- 更廣的適用性
- 返回值是 Promise
await
顧名思義,等待。正常情況下,await命令后面是一個 Promise 對象,返回該對象的結果。如果不是 Promise 對象,就直接返回對應的值。另一種情況是,await命令后面是一個thenable對象(即定義then方法的對象),那么await會將其等同於 Promise 對象。
混合使用
先看示例:
function sleep(ms) { return new Promise(function(resolve, reject) { setTimeout(resolve,ms); }) } async function handle(){ console.log("AAA") await sleep(5000) console.log("BBB") } handle(); // AAA // BBB (5000ms后)
我們定義函數sleep,返回一個Promise。然后在handle函數前加上async關鍵詞,這樣就定義了一個async函數。在該函數中,利用await來等待一個Promise。
Promise優缺點
優點 | 缺點 |
---|---|
解決回調 | 無法監測進行狀態 |
鏈式調用 | 新建立即執行且無法取消 |
減少嵌套 | 內部錯誤無法拋出 |
作者:流眸Tel
鏈接:https://www.jianshu.com/p/b16e7c9e1f9f
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。