为什么要在异步函数中包装await?

时间:2019-06-14 15:33:12

标签: javascript

为什么要有一个异步功能才能使用await?为什么我们不能在没有异步的情况下使用await? JS默认也是异步的,这只会增加混乱。

更新: 我看到一些小伙子搁置了我的问题,所以我会尽力阐述。 我只是好奇为什么这行不通:

some code
let users = await getUsers();
some code

为什么要在异步内部使其正常工作,即

$(async function() {
    some code
    let users = await getUsers();
    some code
});

3 个答案:

答案 0 :(得分:1)

  

JS默认也是异步的...

否,默认情况下,JavaScript不是异步的。 JavaScript的唯一异步功能是相当新添加的:

  • 承诺解决方案
  • async / await

JavaScript通常用于与异步事物进行交互的环境(例如DOM中的事件处理程序,或Node.js中的I / O完成),但是JavaScript不是异步的(除了上述之外)。

在多年{@ 3}}的ECMAScript规范的编辑Allen Wirfs-Brock中,JavaScript ...

  

(具有)一个可观察到的同步执行模型。除了通过Atomics / SAB以外,没有可观察到的共享状态竞争条件。

回到您的问题:

  

为什么要使用await功能才能使用await?

不久之后,the words of就可以完成top level await proposal的工作,而无需使用模块。到了第3阶段。

但是答案是await是使用诺言的句法糖,诺言的规则之一是您要么处理错误,要么将链返回给调用方(这样它就可以处理错误或返回调用者。链接到调用方)。 await不处理错误,因此必须将链返回给调用方。这样做的方式是async函数始终返回一个诺言,并且该诺言链接到诺言await等待。

也就是说,这个:

async function foo() {
    const thingy = await somethingAsyncReturningAPromise();
    return thingy.foo;
}

从概念上讲(但不是从字面上看):

function foo() {
    return somethingAsyncReturningAPromise()
        .then(thingy => thingy.foo);
}

如果somethingAsyncReturningAPromise中出现问题,则foo返回的承诺将被拒绝-错误会传播到调用方。

据我从顶层await提议中得知,它只是允许模块顶层的未处理拒绝为未处理拒绝。因此,就像这段代码会导致未处理的错误一样:

null.doSomething();

异步模块中的以下代码将导致未处理的拒绝:

await somethingThatReturnsAPromiseAndRejects();

答案 1 :(得分:0)

  

为什么要有一个异步功能才能使用await?为什么我们不能在没有异步的情况下使用await?

因为async / await对于承诺来说只是“ 语法糖”。如果该函数是异步的,则它将返回一个Promise。不返回承诺就不可能有“等待”行为。该函数异步的事实必须明确标记。

  

JS默认也是异步的,这只会增加混乱。

此陈述过于“简化”。尽管JS本质上是异步的,但由于事件循环的存在,但这并不意味着每个函数都具有异步行为。这不会增加混乱。您可能由于误解JS的工作原理而感到困惑。您应该阅读有关Promises的内容,当您看到async / await时,这些内容就在幕后。

答案 2 :(得分:0)

JavaScript具有基于任务的并发性。从根本上讲,这意味着代码块(任务)将同步运行而不会被中断,直到达到某个断点(任务结束)为止。这有一些优点:

1)您确实具有并发性,例如网络调用不会同时阻止您的脚本执行其他操作(因此消耗网络请求的任务只有在网络请求完成后才能运行,其他任务可以在此期间完成)。

2)另一方面,您没有并发的突变,这消除了很多问题(let a = 1; a += 1;可以评估为3,您需要使用锁/信号灯来防止这些问题,请参见Java及其他)。

现在async / await允许您定义此类任务:

异步功能可以分为任务,await作为断点:

  let a = 1;
  async function stuff() {
    a = a + 1; // this is totally secure, as no other code might run in the meantime
    a = a + await other(); // this is unsafe, as we await, which means that other tasks might be executed in the meantime.
  }

如果您要“等待非异步函数”,这基本上意味着您将不知道某个函数调用是否同步运行(意味着:同时没有其他代码在运行):

  function dangerous() { await stuff(); }

  let a = 1;
  a = a + dangerous(); // does that work or not? Can a be manipulated in the meantime?

因此,根据您的建议,您基本上将消除任务之间的边界,每个代码可能会在每个任务之间运行。因此,最终会导致混乱,如果您想提高生产力,那么混乱就不好。