ES2017 - 异步与收益率

Dan*_*nny 32 javascript async-await ecmascript-6 ecmascript-2017

我对目前关于将async函数和关键字添加await到下一个EcmaScript的讨论感到困惑.

我不明白为什么有必要在async关键字之前使用function关键字.

从我的观点来看,await关键字等待发电机或承诺的结果一个函数的return应该是足够的.

await应该在普通函数和生成器函数中简单可用,无需额外的async标记.

如果我需要创建一个函数作为结果应该可用await,我只需使用一个promise.

我的理由是这个很好的解释,下面的例子来自:

async function setupNewUser(name) {  
  var invitations,
      newUser = await createUser(name),
      friends = await getFacebookFriends(name);

  if (friends) {
    invitations = await inviteFacebookFriends(friends);
  }

  // some more logic
}
Run Code Online (Sandbox Code Playgroud)

它也可以作为普通函数完成,如果函数的执行将等待完成孔函数,直到满足所有等待.

function setupNewUser(name) {  
  var invitations,
      newUser = await createUser(name),
      friends = await getFacebookFriends(name);

  if (friends) {
    invitations = await inviteFacebookFriends(friends);
  }

  // return because createUser() and getFacebookFriends() and maybe inviteFacebookFriends() finished their awaited result.

}
Run Code Online (Sandbox Code Playgroud)

在我看来,整个功能执行一直持续到下一个滴答(等待履行)完成.与Generator-Function的不同之处在于next()正在触发并更改对象的值和完成字段.一个函数将简单地返回结果,并且触发器是一个函数内部触发器,如while循环.

Ber*_*rgi 18

我不明白为什么有必要async在function关键字之前使用关键字.

出于同样的原因,我们*在生成器函数之前有符号:它们将函数标记为非凡.它们在这方面非常相似 - 它们添加了一个可视标记,该函数的主体本身不会完成运行,但可以与其他代码任意交错.

  • 所述*表示的发电机的功能,这将总是通过消耗它类似于一个迭代返回从外部可被推进(并停止)的发电机.
  • async表示异步函数,它总是返回依赖于其他承诺一个承诺,其执行是并发的其他异步操作(和可能从外部取消).

确实,关键字不是绝对必要的,函数的类型可以通过相应的关键字(yield(*)/ await)是否出现在其正文中来确定,但这会导致代码的可维护性降低:

  • 不易理解,因为你需要扫描整个身体来确定那种
  • 更多的errorprone,因为通过添加/删除这些关键字而不会出现语法错误很容易破坏功能

一个正常的函数,执行将等待完成孔体直到满足所有等待

这听起来像你想要一个阻塞功能,这在并发设置中是一个非常糟糕的主意.


Lee*_*son 15

通过将函数标记为async,您告诉JS始终返回Promise.

因为它总会返回一个Promise,它也可以等待它自己的块内的promise.想象一下它就像一个巨大的Promise链 - 函数内部发生的事情会被有效地固定在它的内部.then()块上,而返回的是.then()链中的最终结果.

例如,这个功能......

async function test() {
  return 'hello world';
}
Run Code Online (Sandbox Code Playgroud)

...返回一个承诺.所以你可以像一个人一样执行它.then().

test().then(message => {
  // message = 'hello world'
});
Run Code Online (Sandbox Code Playgroud)

所以...

async function test() {
  const user = await getUser();
  const report = await user.getReport();
  report.read = true
  return report;
}
Run Code Online (Sandbox Code Playgroud)

大致类似于......

function test() {
  return getUser().then(function (user) {
    return user.getReport().then(function (report) {
      report.read = true;
      return report;
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,传递给的回调都test().then()report作为其第一个参数接收.

生成器(即标记函数*和使用yield关键字)是完全不同的概念.他们不使用Promises.它们有效地允许您在代码的不同部分之间"跳转",从函数内部生成结果,然后跳回到该点并重新开始下一个yield块.

虽然他们觉得有些相似(即'停止'执行直到某些事情发生在其他地方),但async/await只会给你这种错觉,因为它与Promise执行的内部顺序相混淆.它实际上并没有等待 - 当回调发生时它只是在洗牌.

相反,生成器的实现方式不同,因此生成器可以维护状态并进行迭代.再一次,与Promises无关.

这条线路进一步模糊,因为在目前的写作时,对async/await的支持很吓人; Chakracore原生支持它,V8即将推出.与此同时,像Babel这样的转发器允许您编写async/await代码并将其转换为生成器.结论发电机和异步/等待是相同的是错误的; 他们不是......只是碰巧你可以把yield与Promises一起工作的方式混淆得到类似的结果.

更新:2017年11月

Node LTS现在具有本机async/await支持,因此您永远不需要使用生成器来模拟Promises.

  • 非常勤奋的回答 (2认同)

pha*_*aux 7

这些答案都给出了为什么async关键字是好事的有效论据,但它们都没有提到为什么必须将它添加到规范中的真正原因.

原因是这是一个有效的JS pre-ES7

function await(x) {
  return 'awaiting ' + x
}

function foo() {
  return(await(42))
}
Run Code Online (Sandbox Code Playgroud)

根据你的逻辑,会foo()回来Promise{42}还是"awaiting 42"?(返回Promise会破坏向后兼容性)

所以答案是:await是一个常规标识符,它只被视为异步函数中的关键字,因此必须以某种方式标记它们.

有趣的事实:原始规范提出了更轻量级function^ foo() {}的异步语法.


归档时间:

查看次数:

7252 次

最近记录:

7 年,10 月 前