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}`)
  }
}

热饭班长
3.7k 声望434 粉丝

先去做,做出一坨狗屎,再改进。