Promise
對象是一個構造函數,其接受一個函數做爲參數,resolve
、reject
爲這個函數的參數,函數內部通常爲異步執行的代碼,resolve
做爲異步執行完成以後成功的回調,reject
做爲異步執行拋錯的回調。Promise
構造函數能夠理解爲執行異步的過程,其resolve
和reject
爲執行異步調用結果的回調函數。javascript
// 代碼1 var p = new Promise((resolve, reject) => { // 執行一系列的異步執行 // some codes... if (true) { resolve("異步執行成功"); } else { reject("異步執行拋錯"); } }); // fulfilled: 異步執行成功 ; 非fulfilled: 異步執行拋錯
Promise
構造函數返回一個異步執行以後的promise
對象,該對象對異步的結果進一步處理。java
// 代碼2 p .then((res) => { // try catch 手動拋錯 try { // console.log("異步返回成功狀態"); throw Error("錯誤代碼"); } catch(e) { console.log("執行catch"); return Promise.reject(e); } }) .catch((res) => { console.log(res); // 輸出上一個 then 中 catch 的 e return "這裏由錯誤信息過去的數據"; }) .then((res) => { console.log(res); // 若上一個catch執行,輸出:這裏由錯誤信息過去的數據 })
以上代碼執行結果:node
# 結果1 執行catch Error: 錯誤代碼 at p.then (**/promise.js:77:10) at process._tickCallback (internal/process/next_tick.js:109:7) at Module.runMain (module.js:607:11) at run (bootstrap_node.js:423:7) at startup (bootstrap_node.js:147:9) at bootstrap_node.js:538:3 這裏由錯誤信息過去的數據
由代碼2能夠看出,promise
對象狀態爲resolve
的時候,執行then
方法,並且在不拋錯狀況下會持續執行鏈式調用的then
方法,若then
方法拋出異常或者拋出返回Promise.reject()
方法,會轉到執行catch
方法,若catch
方法返回的不是Promise.reject()
方法或者不拋出異常,則全部使用return
返回的數據都會做爲參數傳給下一個then
函數參數的參數,即代碼2中的最後一個then
方法指定函數參數的res
是上一個catch
所return
的數據。es6
var p = new Promise((resolve, reject) => { resolve("ok"); }); p.then((msg) => { console.log(msg); return Promise.reject("then01拋錯"); }).catch((errMsg) => { console.warn(errMsg); }).then(() => { console.log("then02再執行"); }).then(() => { console.log("then03再執行"); return Promise.reject("then03拋錯"); }).catch((errMsg) => { console.warn(errMsg); return "catch02 return 給下一個then指定方法的值"; }).then((msg) => { console.log(msg); });
運行結果以下:bootstrap
這是由於then
方法和catch
方法返回的都是一個promise
對象。then
方法指定的回調函數拋出錯誤會被下一個catch
方法捕獲,多個then
方法執行也是如此。catch
方法會捕獲上一個catch
方法(若是有的話)以後拋錯的錯誤。promise
換言之,不管是
then
方法仍是catch
方法,返回的都是一個promise
對象,其狀態取決於上一個方法指定的函數是否順利執行或者沒有返回Promise.reject()
。瀏覽器
Promise
狀態一旦Promise的狀態變爲resolved或者rejected,就會永久保持該狀態,不會再變。bash
var p = new Promise((resolve, reject) => { resolve("ok"); throw new Error("wrong"); }); p.then((msg) => { console.log(msg); }).catch((errMsg) => { console.warn(errMsg); }); // ok
在Promise的參數函數中,因爲先判定了resolved狀態,因此在以後只會執行then
函數,後面拋出的錯誤會等於沒拋出來。異步
另外,「事件循環」會對拋出的結果有影響。函數
var p = new Promise((resolve, reject) => { resolve("ok"); setTimeout(() => { throw new Error("wrong"); }, 0); }); p.then((msg) => { console.log(msg); }).catch((errMsg) => { console.warn(errMsg); }); // ok // 瀏覽器拋出的錯誤 // index.js:4 Uncaught Error: wrong // at setTimeout (index.js:4) // setTimeout @ index.js:4
在本輪「事件循環」中,promise
對象p
先執行,因此構造函數Promise
的指定函數先輸出‘ok’;在進入到下一次的「事件循環」的時候,因爲Promise
函數體已經執行完畢,故後面拋出的錯誤是在Promise
函數體外拋出的,Promise
函數體沒法捕獲到這個錯誤。
Promise.resolve()
接受一個參數,其返回一個promise
對象的狀態會由於傳入的參數的不一樣而不一樣。
空
返回一個狀態爲resolved
的promise對象,也就是下一步會執行then
方法。
var p = Promise.resolve(); p.then((res) => { console.log("then"); }).catch((res) => { console.log("catch"); }); // then
thenable
對象
var thenable = { then: function (resolve, reject) { console.log("當即執行thenable的then的方法" + Date.now()); resolve("判定以後的信息"); } } var p = Promise.resolve(thenable); p.then((res) => { console.log(res); }); // 當即執行thenable的then的方法1494485393447 // 判定以後的信息 // 至關於 var p = new Promise(function (resolve, reject) { console.log("當即執行thenable的then的方法" + Date.now()); resolve("判定以後的信息"); }); p.then((res) => { console.log(res); }); // 當即執行thenable的then的方法1494485454503 // 判定以後的信息
thenable
對象做爲參數,在執行Promise.resolve(thenable)
方法的時候,會當即執行thenable
對象中的then
方法,而且其返回的Promise
對象的狀態取決於thenable
對象的then
方法執行的是resolve()
仍是reject()
。這種狀況下,就至關於Promise
構造函數以thenable
對象的then
方法做爲參數,實例化一個Promise
實例。
一個非Promise
對象,且不含有then
方法的對象------非thenable
對象
var p = Promise.resolve({ a: 1 }); p.then((res) => { console.log(res); }); // { a: 1 } var p01 = Promise.resolve('Hello Promise!'); p01.then((res) => { console.log(res); }); // Hello Promise!
這種狀況下,Promise.resolve()
的狀態爲resolved
,其接收的參數會做爲then
方法指定函數的參數。
Promise對象
var p01 = new Promise((resolve, reject) => { reject('Throw some error! Come on! You bite me.'); }); var p = Promise.resolve(p01); p.then((res) => { console.log("這是then方法"); }).catch((errMsg) => { console.log(errMsg); }); // Throw some error! Come on! You bite me.
傳入的是一個Promise
對象,Promise.resolve()
返回的對象的狀態就是傳入的Promise
對象的狀態。
Promise.reject(reason)
方法一樣返回一個狀態爲rejected
的Promise
對象實例。值得注意的是,參數reason
(Promise
狀態rejected
的緣由)不管是什麼值,都會傳給返回的Promise
對象的catch方法指定的函數做爲參數。
var p = Promise.reject('Throw some error! Come on! You bite me.'); p.then((res) => { console.log("這是then方法"); }).catch((errMsg) => { console.log(errMsg); }); // Throw some error! Come on! You bite me.
var imgPromise = function (url) { return new Promise((resolve, reject) => { var img = new Image(); img.src = url; img.onload = resolve; img.onerror = reject; }); } imgPromise("http://imgurl") .then((res) => { console.log("圖片加載完成"); }) .catch((res) => { console.log("圖片加載失敗"); }):