Несколько блоков try-catch внутри функции asyn c - PullRequest
2 голосов
/ 04 марта 2020

У меня есть функция asyn c, в которой есть некоторые операции, подобные этой:

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

Или внутри моих асинхронных функций и для оператора:

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 в моем исходном коде - это длина c.

Ответы [ 2 ]

2 голосов
/ 04 марта 2020

Зависит от того, как и где вы хотите обработать сбой.

Один из подходов к « массиву асинхронных задач, выполнение которого может завершиться с ошибкой », выглядит следующим образом:

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 функция, и она имеет тот же эффект, что и ее упаковка в try / catch.

Подробнее здесь , если вы заинтересованы. В разделе «Refactor без 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
}
1 голос
/ 04 марта 2020

Все зависит ... Мое эмпирическое правило - только catch что-то, если вы намереваетесь что-то с ним сделать, то есть некоторая обработка ошибок. Если обработка ошибки будет одинаковой во всех случаях, оберните все это одним try/catch, в противном случае оберните отдельные случаи своим собственным кодом обработки ошибок.

...