博客 / 詳情

返回

異常處理策略

const api = {
  getData: () => {
    return new Promise((resolve) => {
      resolve(undefined);
    });
  },
};

沒有異常處理,會導致程序崩潰

const getLogo = async () => {
  const res = await api.getData()
  return res.logo
}

const main = async () => {
  const logo = await getLogo()
}

main()

加異常處理,但只是簡單打印錯誤信息,程序沒有崩潰,並且輸出的錯誤信息

const getLogo = async () => {
  try {
    const res = await api.getData()
    return res.logo
  } catch (error) {
    // 打印異常信息
    console.error(`getLogo error: ${error}`) 
  }
}

const main = async () => {
  const logo = await getLogo()
}

main()

在前面的基礎上添加業務邏輯,雖然沒有崩潰,但是我們會發現,在getLogo已經失敗的情況下,還是執行了copyLogoToDist,這顯然是不合理的,我們的做法簡單來説只是把異常吞掉了,這會導致後續邏輯在錯誤狀態下繼續執行,可能引發更嚴重的問題

const getLogo = async () => {
  try {
    const res = await api.getData()
    return res.logo
  } catch (error) {
    // 打印異常信息
    console.error(`getLogo error: ${error}`) 
  }
}

const copyLogoToDist = async (logo) => {
  console.log('copyLogoToDist')
  // ...
}

const main = async () => {
  const logo = await getLogo()
  await copyLogoToDist(logo)
}

main()

那麼如何解決上面的問題呢?
方案有兩種:
方案1:判斷getLogo的返回值,也就是logo,然後決定是否執行copyLogoToDist
方案2:在getLogo中拋出異常,讓調用者處理

方案1示例:

const getLogo = async () => {
  try {
    const res = await api.getData()
    return res.logo
  } catch (error) {
    // 打印異常信息
    console.error(`getLogo error: ${error}`) 
  }
}

const copyLogoToDist = async (logo) => {
  console.log('copyLogoToDist')
  // ...
}

const main = async () => {
  const logo = await getLogo()
  // 由於getLogo吞掉了異常,沒有做其他操作,所以getLogo的返回值將會是undefined
  // 這裏的判斷就避免了將異常被延續了
  if (logo) {
    await copyLogoToDist(logo)
  }
}

main()

方案2示例:

const getLogo = async () => {
  try {
    const res = await api.getData()
    return res.logo
  } catch (error) {
    console.error(`getLogo error: ${error}`)
    // 拋出異常
    thrown error
  }
}

const copyLogoToDist = async (logo) => {
  console.log('copyLogoToDist')
  // ...
}

const main = async () => {
  // 在調用處處理異常,當getLogo拋出了異常,就避免了將異常繼續延續下去
  try {
    const logo = await getLogo()
    await copyLogoToDist(logo)
  } catch (error) {
    console.error(`main error: ${error}`)
  }
}

main()

方案1存在的問題:
1 if(logo)的意圖是用來判斷logo是否為合法值的,而不是處理異常的
2 如果getLogo不是一個沒有返回值的接口,那麼在這裏就無法處理了

const main = async () => {
  // createLogo裏面發生了異常,在內部捕獲了
  // createQuickEntry並不知道,然後繼續執行,導致異常被延續
  await createLogo()
  await createQuickEntry()
}

方案2可以解決方案1存在的問題

const main = async () => {
  // createLogo拋出了異常,createQuickEntry就不會被執行了
  try {
    await createLogo()
    await createQuickEntry()
  } catch (err) {
    console.error(`main error: ${error}`)
  }
}
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.