點燈坊

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

Promise 之 Promise.resolve() 與 Async

Sam Xiao's Avatar 2019-09-13

Fulfilled Promise 除了可由 Promise.resolve() 建立外,也可由 ECMAScript 2018 的 async 宣告,此外 Promise.resolve() 還能將 jQuery 的 Thenable Object 轉成真正的 Promise。

Version

macOS Mojave 10.14.6
VS Code 1.38.1
Quokka 1.0.251
ECMAScript 2018

Argument for Any Value

let promise0 = Promise.resolve('Hello World');

promise0.then(x => console.log(x));

let x = await promise0;
console.log(x);

若將任意值傳入 Promise.resolve(),將回傳該值的 fulfilled promise。

可使用 then()await 取得內部值。

resolve000

Argument for Fulfilled Promise

let promise0 = Promise.resolve('Hello World');
let promise1 = Promise.resolve(promise0);

(promise0 === promise1); // ?

當 promise 傳入 Promise.resolve() 時,將回傳相同的 promise。

並沒有所謂的 promise 的 promise,而是回傳相同的 promise

resolve001

Argument for Rejected Promise

let promise0 = Promise.reject(new Error('Something worng'));
let promise1 = Promise.resolve(promise0);

(promise0 === promise1); // ?

當我們將 rejected promise 傳進 Promise.resolve() 時,依然回傳 rejected promise,並沒有因為 Promise.resolve() 而回傳 fulfilled promise。

Promise.resolve() 並不是永遠回傳 fulfilled promise,當我們傳進 promise 時,原本是 fulfilled promise 就回傳 fulfilled promise;原本是 rejected promise 就回傳 rejected promise

resolve002

Argument for Error Object

let promise0 = Promise.resolve(new Error('Something worng'));

promise0
  .then(x => console.log('fulfilled : ', x.message))
  .catch(x => console.log('rejected : '. x.message));

若將 Error object 傳入 Promise.resolve() 時,依然回傳以 Error object 的 fulfilled promise,而非 rejected promise。

resolve003

Return Promise in then()

let promise0 = Promise.resolve('Hello World');
let promise1 = promise0.then(x => Promise.resolve(x));

(promise0 === promise1); // ?

若由 then() 所回傳的 promise,則為全新的 promise,並非如 Promise.resolve() 般回傳同一個 promise。

resolve004

Thenable Object

$.getJSON(API_URL)
  .then(x => console.log(x))
  .catch(e => console.log(e))
  .finally(() => console.log('Fetch completed'));

jQuery 的 getJSON() 並非回傳真正的 promise,只是帶有 then() 的 object,因此也稱為 thenable object 或 promise-like object,也由於不是真的 promise,並沒有 finally() 而執行錯誤。

Promise.resolve($.getJSON(API_URL))
  .then(x => console.log(x))
  .catch(e => console.log(e))
  .finally(() => console.log('Fetch completed'));

Promise.resolve() 可將 thenable object 轉成真的 promise,如此就能真的執行 finally()

Function Return Promise

let fn = x => Promise.resolve(x + 1);

fn(1).then(x => console.log(x));

若想將原本 synchronous function 回傳 promise 成為 asynchronous function,可由 Promise.resolve() 轉換。

resolve005

let fn = async x => x + 1;

let x = await fn(1); // ?

也可使用 ES2018 的 async 修飾 function,使其回傳 promise,也可搭配 await 取代 then() 取得 fulfilled promise。

resolve006

Conclusion

  • Promise.resolve() 對於一般值是回傳其 fulfilled promise,若傳入的是 promise,則回傳原本的 promise,若原本就是 rejected promise,則回傳仍然是 rejected promise
  • 若傳入是 Error object,則回傳 Error object 的 fulfilled promise,而非 rejected promise
  • then() 回傳的 promise 則永遠是全新的 promise
  • Promise.resolve() 可將 jQuery 的 thenable object 轉成真正的 promise
  • 也可使用 ES2018 的 async 取代 Promise.resolve()

Reference

Marius Schulz, Create a Resolved Promise in JavaScript with Promise.resolve()
MDN, Promise.resolve()
MDN, async function