【问题标题】:Async event and exception异步事件和异常
【发布时间】:2018-06-11 07:20:39
【问题描述】:

在 ES7 中,我们将为 JS 提供 asyncawait 关键字。对于常规功能,它看起来很有希望。但是我们如何处理异步事件中的异常呢?

例如

async badFunc()
{
    throw "bad";
}

var reader = new FileReader();
reader.onload = async function ()
{
    await badFunc();
}

根据我的理解,async 函数将是一个语法糖,它将在底层使用Promiseresolvereject 函数。所以只有调用者使用await关键字时才会捕获异常。

在上面的示例中,await badFunc(); 行将捕获异常并重新抛出它。但由于onload 处理程序可能没有在回调中调用await,因此异常将在空虚中丢失。即使window.onerror 也无法捕捉到它。

所以我的问题是。在事件内部使用 await 的正确方法应该是什么,这样异常才不会丢失?

【问题讨论】:

  • 将 await 包裹在 try ... catch 块中
  • @0.sh 我们如何重新抛出它以便全局处理程序有机会做某事?
  • 事件处理程序没有承诺的概念,因此将异步函数分配给事件处理程序似乎毫无意义,除非您处理其中的逻辑。即便如此,你也失去了返回 false 的能力。
  • @Steve,你是说抛出await badFunc()引起的异常吗?
  • 这是 ES2017,不是 ES7。虽然现有帖子直接回答了这个问题,但它有利于控制流到promisify FileReader,而不是在其回调中处理承诺。

标签: javascript async-await ecmascript-2017


【解决方案1】:

你说得对,async-await 只是 Promise 的语法糖。任何 async 函数都会返回一个Promise,当函数返回时resolved,或者当函数抛出异常时rejected

async foo() {
  return 1;
}

const promise1 = foo(); // here we have a promise that will   resolve in 1

async bar() {
  throw new Error('something went wrong');
}

const promise2 = bar(); // here we have a promise that will be rejected with an error.

这些承诺可以像任何常规承诺一样处理,例如:

foo().then(…).catch(…);

async 函数内部,您可以使用 await 关键字。如果它后面跟着一个 Promise(或类似 Promise 的对象),它将暂停异步函数的执行并等待 Promise 解决。如果 promise 解决了它的结果将被用作表达式的结果。如果被拒绝,会在使用await的那一行抛出异常。

例子:

const promise3 = async baz() {
  const boo = await foo(); //  (1)
  const zoo = await bar(); // (2)
}

(1) 在这一行暂停,等待 promise 解决;承诺解决后,boo 变为等于 1。

(2) 在这一行暂停,等待 promise 解决; Promise 拒绝后,抛出异常。

await 抛出的错误可以使用 try…catch 来捕获。如果不是,它们会冒泡,这意味着promise3 将被拒绝。

【讨论】:

    【解决方案2】:
    async badFunc()
    {
        throw "bad";
    }
    
    var reader = new FileReader();
    reader.onload = function ()
    {
        (async()=>{
            await badFunc();
        })().then(()=>()).catch(e=>console.log(e))
    }
    

    我已将异步事件处理程序替换为调用内部异步 IIFE 的普通事件处理程序。 console.log(e) 可以替换为您认为有帮助的任何错误例程。

    请注意,您可以通过在末尾放置“return x”来从处理程序返回标准值——这将始终在评估 badFunc 的 Promise 之前触发,即使它被拒绝。您不能根据内部承诺的 resolved 状态返回值,除非您的回调期望并将评估 Promise 返回值。您可以链接到另一个事件侦听器。

    另外,虽然window.onerror 不会捕捉到错误,但unhandledrejection 会在 Chrome 和其他一些浏览器中捕捉到它。 Firefox 显然不会。这对于调试代码来说已经足够了,但在生产环境中无法捕捉到任何东西。

    【讨论】:

      猜你喜欢
      • 2019-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-09
      • 1970-01-01
      • 1970-01-01
      • 2022-07-07
      相关资源
      最近更新 更多