iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 7
1
Modern Web

JavaScript 之旅系列 第 7

JavaScript 之旅 (7):Async Functions & await (2)

Promisethen()catch() vs. async / awaittry-catch

非同步一般處理

處理一個非同步行為

若用 Promisethen() 可能會像這樣寫:

// 模擬發 API,但只會成功 (fulfilled),回傳的資料為 "OK"
function fakeFetch(url) {
  return Promise.resolve('OK');
}

function asyncFunc() {
  return fakeFetch().then(value => {
    console.log(value);
  });
}

asyncFunc();
// "OK"

若改用 async / await 的寫法:

// 模擬發 API,但只會成功 (fulfilled),回傳的資料為 "OK"
async function fakeFetch() {
  return 'OK';
}

async function asyncFunc() {
  const result = await fakeFetch();
  console.log(result);
}

asyncFunc();
// "OK" 或 "Oops"

依順序處理多個非同步

若用 Promisethen()catch(),可能會像這樣寫:

function asyncFunc() {
  return fakeFetch()
    .then(result1 => {
      console.log(result1);
      return fakeFetch();
    })
    .then(result2 => {
      console.log(result2);
    });
}

若改用 async / await 就能使用 try-catch 的寫法:

async function asyncFunc() {
  const result1 = await fakeFetch();
  console.log(result1);
  const result2 = await fetchUser();
  console.log(result2);
}

可以看到若要按順序處理多個非同步,就會非常麻煩,需要在 then() 的 callback 內寫另一個非同步的處理,若是用 async / await 就會很像同步的寫法。

同時處理多個非同步

常見的用法是使用 Promise.all(),可同時處理多個非同步,但必須所有傳入的值都是 fulfilled 才會讓 Promise.all() 回傳的 promise fulfilled,否則會 rejected。

若用 Promisethen()catch(),可能會像這樣寫:

function asyncFunc() {
  return Promise.all([
    fakeFetch(),
    fakeFetch()
  ])
  .then(([result1, result2]) => {
    console.log(result1);
    console.log(result2);
  });
}

若改用 async / await 就能使用 try-catch 的寫法:

async function asyncFunc() {
  const [result1, result2] = await Promise.all([
    fakeFetch(),
    fakeFetch()
  ]);
  console.log(result1);
  console.log(result2);
}

非同步錯誤處理

處理一個非同步行為

若用 Promisecatch() 可能會像這樣寫:

// 模擬發 API,但只會回傳 "OK"
function fakeFetch(url) {
  return Promise.reject(new Error('Oops'));
}

function asyncFunc() {
  return fakeFetch()
    .then(value => {
      console.log(value);
    })
    .catch(error => {
      console.log(error.message);
    });
}

asyncFunc();
// "Oops"

若改用 async / await 就能使用 try-catch 的寫法:

// 模擬發 API,但只會成功 (rejected),錯誤訊息為 "Oops"
async function fakeFetch() {
  throw new Error('Oops');
}

async function asyncFunc() {
  try {
    const result = await fakeFetch();
    console.log(result);
  } catch (error) {
    console.log(error.message);
  }
}

asyncFunc();
// "Oops"

依順序處理多個非同步

若用 Promisethen()catch(),可能會像這樣寫:

function asyncFunc() {
  return fakeFetch()
    .then(result1 => {
      console.log(result1);
      return fakeFetch();
    })
    .then(result2 => {
      console.log(result2);
    })
    .catch(error => {
      console.log(error.message);
    });
}

若改用 async / await 就能使用 try-catch 的寫法:

async function asyncFunc() {
  try {
    const result1 = await fakeFetch();
    console.log(result1);
    const result2 = await fetchUser();
    console.log(result2);
  } catch (error) {
    console.log(error.message);
  }
}

上面的處理方式是每個非同步都由同一個 catch 來接收錯誤,若想分別處理錯誤,可以用 catch() 來處理:

async function asyncFunc() {
  const result1 = await fakeFetch()
    .catch(error => {
      console.log(error.message);
    });
  console.log(result1);

  const result2 = await fakeFetch()
    .catch(error => {
      console.log(error.message);
    });
  console.log(result2);
}

同時處理多個非同步

若用 Promisethen()catch(),可能會像這樣寫:

function asyncFunc() {
  return Promise.all([
    fakeFetch(),
    fakeFetch()
  ])
  .then(([result1, result2]) => {
    console.log(result1);
    console.log(result2);
  })
  .catch(error => {
    console.log(error.message);
  });
}

若改用 async / await 就能使用 try-catch 的寫法:

async function asyncFunc() {
  try {
    const [result1, result2] = await Promise.all([
      fakeFetch(),
      fakeFetch()
    ]);
    console.log(result1);
    console.log(result2);
  } catch (error) {
    console.log(error.message);
  }
}

上一篇
JavaScript 之旅 (6):Async Functions & await (1)
下一篇
JavaScript 之旅 (8):Promise.prototype.finally()
系列文
JavaScript 之旅30

尚未有邦友留言

立即登入留言