Расширенный try / catch / finally в Javascript и Typescript

Подробно рассмотрим реализацию блока try-catch-finally-block.

Обработка ошибок в Javascript и Typescript

Всякий раз, когда во время выполнения происходит ошибка, она «выкидывается» в Javascript и Typescript, как это имеет место в большинстве языков программирования. Необработанные выбросы ошибок приведут к сбою вашего приложения или службы, что приведет к наихудшему пользовательскому опыту. Если происходит ошибка, любой несохраненный прогресс теряется, и пользователи потенциально могут начать длительный процесс (например, если пользователь регистрировался на платформе, предоставляя много информации) снова и снова. В результате эти пользователи, скорее всего, никогда больше не будут использовать ваш продукт, так как доверие было потеряно.

Чтобы справиться с такими случаями, можно «отловить» ошибку. Чтобы отловить ошибки в Javascript и Typescript, вы просто заключаете свой код в блок «try», за которым следует блок «catch».

async function getData(){
  try {
    // Call a dummy async 'fetch'-functoin
    const result = await fetch();
    return { result };
  } catch(error) {
    return { error };
  }
}

// ... later in your code ....

const { result, error } = await getData();

if (error){
  // ... handle error case.
}

// Access the results.

В результате ошибка не распространяется на всю систему, что приводит к сбою, а обрабатывается непосредственно в рамках вашего кода. Приложение или служба не выйдет из строя, и можно применить стратегию устранения ошибки для обработки ошибки.

Особое обращение с блоком «finally»

В качестве дополнительного шага для обработки ошибок Javascript и Typescript предоставляют дополнительное ключевое слово «finally». Такой блок «finally» выполняет любой код в пределах своей области действия после того, как были выполнены как блок «try», так и блок «catch» (если произошла ошибка).

// This function is absolutely save
// to call. It fetches some data and 
// optionally catches a potential error.
//
// After everything's done, a 'finally'
// sends the error to our backend for logs,
// if there was any.
async function getData(){
  // In this case, we store the result
  // and error in mutable variables,
  // then return both.
  let result: Result;
  let error: Error;
  
  try {
    // Call a dummy async 'fetch'-function
    result = await fetch();
  } catch(e) {
    error = e;
  } finally {
    // After the whole try/catch has been
    // processed, we can log the error.
    if(error){
      await trackErrorInCloud(error);
    }
  }
  
  return { result, error };
}

// ... same as before ...

Но подождите, это еще не все! Знаете ли вы, что блок «finally» выполняется, даже если вы возвращаете результат в блоке «try» или «catch»? Вот пример того, что я имею в виду.

// Same as the example before, but
// now we directly return from within
// each code block. And this is where
// a side effect can happen.
async function getData(){
  try {
    const result = await fetch();
    return { result };
  } catch(error) {
    return { error }
  } finally {
    //
    // WATCH OUT!
    //
    // Just for demo purpose, but this
    // line of code will override both
    // the return in 'try' as well as 'catch'!
    //
    // Returning inside of 'finally' is therefore
    // dangerous and will lead to hard-to-debug 
    // issues.
    return { finally: true };
  }
}

// data === { finally: true }
const data = await getData();
// Here's a better use case for
// finally.
async function getData(){
  let error: Error;
  
  try {
    const result = await fetch();
    return { result };
  } catch(e) {
    error = e;
    return { error }
  } finally {
    // No return in finally,
    // so it's safe to use.
    if(error){
      await logInCloud()
    }
  }
}

// if no error === { result: ... }
// if error === { error: ... }
const data = await getData();

Резюме

Как вы видели, обработка ошибок в Javascript и Typescript довольно проста и позволяет избежать полного сбоя вашего приложения. Специальную обработку возврата результатов в блоках «try» и «catch» полезно знать при использовании блока «finally», но не следует злоупотреблять этим, чтобы избежать реализации кода в стиле анти-шаблона.

Предложения

Связанные

Языки