Лучшая практика обработки исключений Node.js — после Async/Await

Их уже вопрос по этой теме

Оптимальная практика обработки исключений Node.js

который устарел, а ответы очень устарели, domains с тех пор даже устарели.

Теперь в сценарии Post Async/Await Node.js мы не должны рассматривать синхронные и асинхронные случаи аналогичным образом и генерировать исключения в функциях синхронизации и отклонять обещания в асинхронных функциях вместо возврата экземпляра Error в первом случае.

let divideSync = function(x,y) {
    // if error condition?
    if ( y === 0 ) {
        // "throw" the error 
        throw new Error("Can't divide by zero exception")
    }
    else {
        // no error occured, continue on
        return x/y
    }
}

Моделирование асинхронной операции деления

let divideAsync = function(x, y) {

  return new Promise(function(resolve, reject) {

    setTimeout(function() {
      // if error condition?
      if (y === 0) {
        // "throw" the error safely by rejecting the promise
        reject (new Error("Can't divide by zero exception"));
      } else {
        // no error occured, continue on
        resolve(x / y)
      }
    }, 1000);
  })

};

Таким образом, синхронные и асинхронные исключения могут обрабатываться единообразно.

let main = async function () {
    try {
        //const resultSync = divideSync(4,0);
        const resultAsync = await divideAsync(4,0);
    }
    catch(ex) {
        console.log(ex.message);
    }

}

person adnan kamili    schedule 23.09.2016    source источник


Ответы (1)


Ответы из Node.js Best Practice Exception Handling устарели и сильно устарели.

Не так много. Этот ответ со списком из эта хорошо поддерживаемая запись в блоге весьма актуальна.
Официальное руководство по node.js всегда полезно прочитать, и общий подход не сильно изменился.

Так что же изменилось?

  • Домены сломаны и устарели. Ну, это старые новости.
  • Типичные «обратные вызовы в стиле узла» с их параметром error-first, которые запускаются ровно один раз, больше не должны использоваться. Этот простой стиль последовательного асинхронного кодирования со всеми его проблемами был заменен промисами и async/await. (Примечание: генераторы событий и т. д. — это другой случай)
  • process.on('uncaughtException') дополняется process.on('unhandledRejection')
  • обещания также перехватывают ошибки программиста, если используются правильно. Для скучного последовательного асинхронного кода они могут заменить домены.

Так что же это означает для общего кода?

Разве мы не должны одинаково рассматривать случаи синхронизации и асинхронности и генерировать исключения в функциях синхронизации и отклонять промисы в асинхронных функциях вместо того, чтобы возвращать экземпляр Error?

Да, точно. Вы должны отказаться от своих обещаний с Errors (или throw их от async functions).

Обратите внимание, что вам редко придется звонить reject самостоятельно. С промисами вы должны иметь возможность throw в своем коде. Если вы не можете, вы, вероятно, используете их неправильно, и ошибки программиста также не будут обнаружены.

Золотое правило для этого кода: Никогда не используйте обратные вызовы, которые не являются обратными вызовами промисов. «Обратные вызовы Promise» относятся к аргументам new Promise, then и catch и, возможно, к некоторым пользовательским методам вашей библиотеки (например, finally). Вот где в приведенном выше примере кода есть проблема. Написано правильно, должно читаться

async function divideAsync(x, y) {
    await new Promise(resolve =>
        setTimeout(resolve, 1000) // don't even pass a function expression
    );
    if (y === 0) {
        throw new Error("Can't divide by zero exception");
    } else {
        return x / y;
    }
}
person Bergi    schedule 23.09.2016
comment
Итак, как правило, если асинхронная функция использует асинхронность, выдает ошибку, а если нет, то отклоняет ошибку. - person adnan kamili; 23.09.2016
comment
Нет, даже если функция не использует синтаксис async, но использует промисы, вы можете и должны throw (или return Promise.reject(…), если хотите) использовать обратные вызовы промисов, например divideAsync = (x, y) => new Promise(r => setTimeout(r, 1000)).then(() => { if (y === 0) throw new Error(…) else return x / y }) - person Bergi; 23.09.2016
comment
Почему исключение не перехватывается (необрабатывается), если я выдаю ошибку в своей версии кода - person adnan kamili; 23.09.2016
comment
Потому что вы добавляете обратный вызов setTimeout, а не обратный вызов обещания. См. также здесь - person Bergi; 23.09.2016