Promise.resolve 與 Promise.reject

Promise.rejectPromise.resolve只用於單純的傳入物件、值(理由)或外部的 thenable 物件,轉換為 Promise 物件的場合

Promise.resolve是一個靜態方法,也就是說它前面一定要加上Promise這樣呼叫的方法。Promise.resolve等於是要產生 fulfilled(已實現)狀態的 Promise 物件,它相當於直接回傳一個以then方法實現的新 Promise 物件,帶有傳入的參數值,這個方法的傳入值有三種,相當於then方法中 onFulfilled 函式的回傳值(上一章的內容中有說),語法如下:

Promise.resolve(value)
Promise.resolve(promise)
Promise.resolve(thenable)

直接用Promise.resolve代表這個新的 Promise 物件的狀態是直接設定為 fulfilled(已實現)狀態,這方法只是方便產生根(第一個)Promise 物件使用的,也就是除了用建構式的new Promise()外,提供另一種方式來產生新的 Promise 物件。下面為範例:

Promise.resolve('Success').then(
  function(value) {
    console.log(value) // "Success"
  },
  function(value) {
    // 不會被呼叫
  }
)

Promise.reject剛好與Promise.resolve相反,等於是要產生 rejected(已拒絕)狀態的新 Promise 物件。範例如下:

Promise.reject(new Error('fail')).then(
  function(error) {
    // 不會被呼叫
  },
  function(error) {
    console.log(error) // Stacktrace
  }
)

Promise.rejectPromise.resolve的實作的程式碼隱藏了在內部關於 Promise 物件產生的過程,前面有提到我們不能用沒有 executor 傳入參數的 Promise 建構式來產生新的物件實體,會有錯誤發生。這兩個靜態方法,它們在實作時的確有產生沒有 executor 傳入參數的 Promise 雛形(中介)物件,只是它還不算真正會被回傳出來的 Promise 物件實體。理由主要當然是不讓程式設計師自由控制 Promise 的狀態,要改變 Promise 的狀態只有靠程式碼的執行結果才行。例如下面這一段程式碼(出自 es6-promise):

var promise = new Constructor(noop) //noop是沒有內容的函式
_resolve(promise, object) //_resolve是內部函式,object是Promise.resolve傳入參數值
return promise

Promise.rejectPromise.resolve與使用 Promise 建構式的方式,在使用上仍然有大的不同,executor 傳入參數可以讓程式設師自訂 Promise 產生的過程,而且在產生的過程中是 throw safety(安全)的。以下面的例子來說明:

//方式一: 使用Promise建構式

function initPromise1(someObject) {
  return new Promise(function(resolve) {
    if (typeof someObject !== 'object') throw new Error('error occured')
    else resolve(someObject)
  })
}

//方式二: 使用Promise.resolve+throw

function initPromise2(someObject) {
  if (typeof someObject !== 'object') throw new Error('error occured')
  else return Promise.resolve(someObject)
}

//方式三: 使用Promise.resolve+Promise.reject

function initPromise3(someObject) {
  if (typeof someObject !== 'object')
    return Promise.reject(new Error('error occured'))
  else return Promise.resolve(someObject)
}

//測試用
initPromise1(1)
  .then(value => {
    console.log(value)
  })
  .catch(err => {
    console.log(err.message)
  })

如果此時傳入的someObject不是物件類型,方式二會直接 throw 出例外,造成程式中斷,與 Promise 結構中對錯誤的處理方式不同,只有方式一或方式三可以正常的處理錯誤。

上面的例子是太過簡單,如果initPromise函式中的程式碼很複雜的時候,你在回傳Promise.rejectPromise.resolve前發生例外,是完全沒辦法控制的。

結論

Promise.rejectPromise.resolve只用於單純的傳入物件、值或外部的 thenable 物件,轉換為 Promise 物件的場合。如果你要把一整段程式碼語句或函式轉為 Promise 物件,不要用這兩個靜態方法,要使用 Promise 建構式來產生物件才是正解。

註: 在 Promises/A+ 標準中並沒有關於Promise.rejectPromise.resolve的定義,它們是依據 ES6 Promise 標準中的實作。

Last updated