點燈坊

失くすものさえない今が強くなるチャンスよ

Promise 之 Promise.reject() 與 Throw

Sam Xiao's Avatar 2019-09-20

Promise 有 Fulfilled Promise 與 Rejected Promise 兩種,其中 Fulfilled Promise 可由 Promise.resolve() 建立;而 Rejected Promise 則須由 Promise.reject()Throw 建立。

Version

macOS Mojave 10.14.6
VS Code 1.38.1
Quokka 1.0.250
ECMAScript 2018

Promise.reject()

let fetchData = () => Promise.resolve('Hello World');

fetchData().then(x => {
  console.log(x);
  return Promise.reject(new Error('Something wrong'));
}).catch(e => console.log(e.message));

若想在 fulfilled handler 內自行建立 rejected promise,可先建立 Error object,再由 Promise.reject() 包成 rejected promise。

由於 catch() callback 中的 eError object,必須使用 e.message 才能取得 Something wrong

reject002

Throw

let fetchData = async () => 'Hello World';

fetchData().then(x => {
  console.log(x);
  throw new Error('Something wrong');
}).catch(e => console.log(e.message));

也可在 fulfilled handler 中直接使用 throw 建立 rejected promise,其中 throw 就是 Promise.reject() 的 syntatic sugar。

reject003

Try Catch

let fetchData = async () => 'Hello World';

try {
  let x = await fetchData();
  console.log(x);
  throw new Error('Something wrong');
} catch(e) {
  console.log(e.message);
}

throw 除了能用在 fulfilled handler 外,也能用在 try catch block 中,如此更符合 imperative 與 synchronous 習慣。

但別忘了 throw 是 syntatic sugar,當 throw 搭配 await 時,它產生的是包裹 Error object 的 rejected promise。

reject004

String or Error Object ?

let fetchData = () => Promise.resolve('Hello World');

fetchData().then(x => {
  console.log(x);
  return Promise.reject('Something wrong');
}).catch(e => console.log(e));

以語法而言,我們的確能將 string 傳給 Promise.reject(),如此將回傳包裹 string 的 rejected promise, catch() callback 的 e 就可直接抓到 Something wrong

reject005

不過 Error object 畢竟有完整的 stack trace 可用,對於 debug 有幫助。

MDN 也是建議產生 Error object 的 rejected promise。

Conclusion

  • Promise.reject() 為標準產生 rejected promise 方式
  • throwPromise.reject() 的 syntatic sugar,尤其放在 try catch block 很方便,但別忘了它本質仍是包裹 Error object 的 rejected promise
  • Rejected promise 也可直接包裹 string 即可,但不像 Error object 有完整 stack trace,實務上建議使用 Error object 的 rejected promise

Reference

Marius Schulz, Create a Rejected Promise in JavaScript
MDN, Promise.reject()