Правильно Попробуйте... Синтаксис Catch с использованием Async/Await

Мне нравится плоскость новой функции Async/Await, доступной в Typescript и т.д. Однако я не уверен, что мне нравится факт, что я должен объявить переменную I'm await ing снаружи блока try...catch, чтобы использовать его позже. Например:

let createdUser
try {
    createdUser = await this.User.create(userInfo)
} catch (error) {
    console.error(error)
}

console.log(createdUser)
// business
// logic
// goes
// here

Пожалуйста, поправьте меня, если я ошибаюсь, но лучше всего не размещать несколько строк бизнес-логики в теле try, поэтому я остаюсь только с альтернативой объявления createdUser за пределами блок, назначая его в блоке, а затем используя его после.

Какова наилучшая практика в этом случае?

Ответ 1

Кажется, лучше всего не размещать несколько строк бизнес-логики в теле try.

На самом деле я бы сказал, что так оно и есть. Обычно вы хотите catch исключить все исключения из работы со значением:

try {
    const createdUser = await this.User.create(userInfo);

    console.log(createdUser)
    // business logic goes here
} catch (error) {
    console.error(error) // from creation or business logic
}

Если вы хотите поймать и обрабатывать ошибки только из обещания, у вас есть три варианта:

  • Объявите переменную снаружи и ветвь в зависимости от того, было ли исключение или нет. Это может принимать различные формы, например

    • присвоить значение по умолчанию переменной в блоке catch
    • return раннее или повторное throw исключение из блока catch
    • установить флаг, поймал ли блок catch исключение и проверил его в состоянии if
    • проверить значение переменной, которая была назначена

    let createdUser; // or use `var` inside the block
    try {
        createdUser = await this.User.create(userInfo);
    } catch (error) {
        console.error(error) // from creation
    }
    if (createdUser) { // user was successfully created
        console.log(createdUser)
        // business logic goes here
    }
    
  • Проверяйте пойманное исключение для его типа и обрабатывайте его или восстанавливайте его на основе этого.

    try {
        const createdUser = await this.User.create(userInfo);
        // user was successfully created
        console.log(createdUser)
        // business logic goes here
    } catch (error) {
        if (error instanceof CreationError) {
            console.error(error) // from creation
        } else {
            throw error;
        }
    }
    

    К сожалению, стандартный JavaScript (по-прежнему) не поддерживает синтаксис для условных исключений.

  • Используйте then с двумя обратными вызовами вместо try/catch. Это действительно наименее уродливый способ и моя личная рекомендация также для его простоты и правильности, не полагаясь на помеченные ошибки или взгляды на результат, чтобы отличать выполнение и отказ от обещания:

    await this.User.create(userInfo).then(createdUser => {
        // user was successfully created
        console.log(createdUser)
        // business logic goes here
    }, error => {
        console.error(error) // from creation
    });
    

    Конечно, это связано с недостатком введения функций обратного вызова, что означает, что вы не можете так легко break/continue делать циклы или делать ранние return из внешней функции.

Ответ 2

Другой более простой подход - добавить .catch к функции обещания. например:

const createdUser = await this.User.create(userInfo).catch( error => {
// handle error
})