Подтвердить что ты не робот

Могу ли я поймать ошибку из async без ожидания?

Могут ли быть обнаружены ошибки от не ожидаемого асинхронного вызова, отправлены в исходный инкапсулирующий try/catch или поднять неперехваченное исключение?

Вот пример того, что я имею в виду:

async function fn1() {
    console.log('executing fn1');
}

async function fn2() {
    console.log('executing fn2');
    throw new Error('from fn2');
}

async function test() {
    try {
        await fn1();
        fn2();
    }
    catch(e) {
        console.log('caught error inside test:', e);
    }
}

test();

В этом случае ошибка, выброшенная из fn2, будет проглатываться молча, и определенно не будет обнаружена исходная try/catch. Я считаю, что это ожидаемое поведение, так как fn2, скорее всего, сбрасывается в цикл событий, чтобы закончить в какой-то момент в будущем, а test не заботится о том, когда он заканчивается (что является намеренным).

Есть ли способ гарантировать, что ошибки не были случайно проглочены такой структурой, если не положить внутри try/catch try/catch и сделать что-то вроде испускания ошибки? Я бы даже согласился на непродуманную ошибку, не зная, как ее поймать, я думаю - я не ожидаю, что брошенные ошибки станут типичным потоком программы с тем, что я пишу, но проглатывание ошибок делает его относительно раздражающим для отладки.

Боковое замечание, я использую Babel для перевода кода с использованием преобразования babel-runtime и выполнения его с помощью node.

4b9b3361

Ответ 1

Работа с необработанными отклоненными нативными обещаниями (а async/await использует нативные обещания) - теперь эта функция поддерживается в V8. Он использовался в последней версии Chrome для вывода отладочной информации, когда отклоненное обещание не обрабатывается; попробуйте следующее на Вавилонском репл:

async function executor() {
  console.log("execute");
}

async function doStuff() {
  console.log("do stuff");
  throw new Error("omg");
}

function handleException() {
  console.error("Exception handled");
}

(async function() {
  try {
      await executor();
      doStuff();
  } catch(e) {
      handleException();
  }
})()

Вы видите, что даже если исключение из doStuff() потеряно (поскольку мы не используем await при его вызове), Chrome регистрирует, что отклоненное обещание не было обработано на консоли:

Screenshot

Это также доступно в Node.js 4. 0+, хотя требуется прослушивание специального события unhandledRejection:

process.on('unhandledRejection', function(reason, p) {
    console.log("Unhandled Rejection at: Promise ", p, " reason: ", reason);
    // application specific logging, throwing an error, or other logic here
});

Ответ 2

Если вы знакомы с promises, используйте их. Если нет, вы можете попробовать этот пример, чтобы сделать код более асинхронным:)

function fn1(callback) {
    console.log('executing fn1');
    callback({status: true});
}

function fn2(callback) {
    console.log('executing fn2');
    callback({status: false});
}

function test() {
    fn1(function(result) {
        console.log('fn1 executed with status ' + result.status);
    });

    fn2(function(result) {
        console.log('fn2 executed with status ' + result.status);
        if (result.status == false) {
            console.log('error in fn2');
        }
    });
}

test();