首页 > 解决方案 > 异步函数中的多个 try-catch 块

问题描述

我有一个异步函数,其中有一些这样的操作:

async function myAsyncFunction(argument) {

  let arrayTasks = [
    { 
      const run = async () => {
        let response = await getDataAsync();
      }
    },
    { 
      const run = async () => {
        let response = await getDataAsync();
      }
    }
  ]

  for (const index in arrayTasks) {
      await arrayTasks[index].run();
  }
}

上面的函数是我的代码的简化版本,它可以工作。但我不确定我需要在哪里放置 try-catch 块:

包装所有内容功能:

async function myAsyncFunction(argument) {
  try{
    // All code
  }catch (e) {
    // catch code
  }
}

或者在我的 asyncs 函数和 for 运算符中:

async function myAsyncFunction(argument) {

  let arrayTasks = [
    { 
      const run = async () => {
        try{
          let response = await getDataAsync();
        }catch (e) {
          // catch code
        }
      }
    },
    { 
      const run = async () => {
        try{
          let response = await getDataAsync();
        }catch (e) {
          // catch code
        }
      }
    }
  ]

  for (const index in arrayTasks) {
    try{
      await arrayTasks[index].run();
   }catch (e) {
     // catch code
   }

  }
}

什么是正确的方法?该arrayTasks变量是我原始代码的动态长度。

标签: javascriptasync-await

解决方案


取决于您要处理故障的方式和位置。

“执行可能失败的异步任务数组”的一种方法是这样的模式:

async function myAsyncFunction(argument) {

  const success = async res => ({ success: await res }) // Promise<{success: res}>
  const error = async err => ({ error: await err }) // Promise<{error: e}>

  const arrayTasks = [
    { 
      run: async () => getDataAsync()
      }
    },
    { 
      run: async () => getDataAsync()
    }
  ]

   const runWithResult = task => task.run().then(success).catch(error)

   const outcomes = await Promise.all(arrayTasks.map(runWithResult))

   console.log(outcomes) // array of {error: e} | {success: res}

}

您可以将.catch()处理程序链接到函数上,它与将其包装在/async中具有相同的效果。trycatch

更多在这里,如果你有兴趣。“没有 fp-ts 的重构”部分展示了如何将该数组从 减少[{error: e} | {success: res}]{error: [], success: []},这更容易使用:

const { error, success } = outcomes.reduce((acc, o) => o.error ? 
    { error: [...acc.error, o.error], success: acc.success } :
    { error: acc.error, success: [...acc.success, o.success] }, 
    { error: [], success: [] })

这是一种称为 FP 类型Either- 操作可能会返回“任一”(在这种情况下)值或错误。

您的代码不会使用这种方法抛出。

如果您知道某事可能会失败,那并不例外。例外情况是发生一些意外故障,恕我直言。

提前知道的“可能失败的任务”只需要编写错误路径代码即可。

如果您采用这种方法,我建议将其构建为一流的状态缩减机,如下所示:

// Takes an array of async tasks that may throw of shape {run: () => Promise<result>}
// Returns Promise<{error: error[], success: result[]}>

async function executeAsyncTasks(arrayOfAsyncTasks) {
  const success = async res => ({ success: await res }) // Promise<{success: res}>
  const error = async err => ({ error: await err }) // Promise<{error: e}>

  const runWithResult = task => task.run().then(success).catch(error)
  const outcomes = await Promise.all(arrayOfAsyncTasks.map(runWithResult))

  const outcomesFlat = outcomes.reduce((acc, o) => o.error ? 
    { error: [...acc.error, o.error], success: acc.success } :
    { error: acc.error, success: [...acc.success, o.success] }, 
    { error: [], success: [] })
  return outcomesFlat
}

推荐阅读