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

могут ли ошибки из не ожидаемого асинхронного вызова быть пойманы, отправлены в оригинальную инкапсуляцию 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 внутренний fn2 и делать что-то вроде испуская ошибка? Я бы даже согласился на необработанную ошибку, не зная, как ее поймать, я думаю-я не ожидаю, что брошенные ошибки будут типичным потоком программы с тем, что я пишу, но проглатывание ошибок делает его относительно раздражающим отлаживать.

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

2 ответов


работа с необработанными отклоненными собственными обещаниями (и 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 регистрирует, что отклоненное обещание было необработано консоль:

Это также доступно в узел.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
});

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

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();