7

我试图更好地理解async functionJavaScript 中的 an 在技术上是什么,即使我基本上知道如何使用它们。

许多对 async/await 的介绍让人相信一个async函数基本上只是一个承诺,但显然不是这样(至少不是Babel6 转译的代码):

async function asyncFunc() {
  // nop
}

var fooPromise = new Promise(r => setTimeout(r, 1));

console.clear();

console.log("typeof asyncFunc is", typeof asyncFunc); // function
console.log("typeof asyncFunc.next is", typeof asyncFunc.next); // undefined
console.log("typeof asyncFunc.then is", typeof asyncFunc.then); // undefined

console.log("typeof fooPromise is", typeof fooPromise); // object
console.log("typeof fooPromise.next is", typeof fooPromise.next); // undefined
console.log("typeof fooPromise.then is", typeof fooPromise.then); // function

await尽管如此,承诺绝对是可能的,例如await fooPromise().

  • async funtion它自己的东西并且await与承诺兼容吗?

  • 并且,有没有办法区分简单functionasync function运行时(以 Babel 兼容的方式)?

4

2 回答 2

9

异步函数是一个返回 promise的函数。它可以帮助您处理一系列异步操作一个接一个发生的情况:

function asyncFunc() {
  return doSomethingAsync() // doSomethingAsync() returns a promise
    .then(() => {
      // do some stuff
      return doSomethingElseAsync(); // returns a promise
    })
    .then(something => {
      // do some stuff
      return doSomethingElseEntirelyAsync(something); // returns a promise
    });
}

转向

async function asyncFunc() {
  await doSomethingAsync(); // awaits for a promise
  // do some stuff
  let something = await doSomethingElseAsync(); // awaits for a promise
  // do some stuff
  return doSomethingElseEntirelyAsync(something); // returns the final promise
  // Note that even if you return a value, like return 5, the function as a whole
  // still returns a promise!
}

它读起来好多了,即使它们是异步的,您也可以使用诸如 try/catch 和 for 循环之类的普通工具来使用它们。

异步函数不是 Promise的替代品,它们是它们之上的糖,用于处理您有许多顺序异步操作的特定情况。

因为await基本上只是“等待这个承诺”,你仍然可以使用很酷的聚合方法Promise.all()Promise.race()等待几个(或几个)承诺的结果。

我不熟悉在运行时区分两者的方法,因为与类一样,异步函数只是 Promises 之上的糖。(虽然可能有一些技巧,比如使用函数.toString并解析结果,但我不计算这些)。

于 2016-01-12T09:38:35.597 回答
0

这对async/await是一种机制,可让您以同步风格编写异步代码,在我看来,这是迄今为止处理异步代码最简单和可读的语法(另请参阅这篇文章)。语法的力量实际上在于其await工作方式。但是为了在await函数体内使用,函数必须以 . 为前缀async

如果您需要更多信息,这里有一个规范async/await

Babel 5 中的当前实现基于https://github.com/facebook/regenerator。正如您在转译代码中看到的那样,该函数被编译为:

function asyncFunc(which, one, two) {
  return regeneratorRuntime.async(function asyncFuncMaybe$(context$1$0) {
...

如果你在 Babel 的babel-regenerator-runtime包中挖掘,你会发现 Facebook 的代码。在第 205 行,您会发现:

// Note that simple async functions are implemented on top of
// AsyncIterator objects; they just return a Promise for the value of
// the final result produced by the iterator.
runtime.async = function(innerFn, outerFn, self, tryLocsList) {
...

为了转译到 ES5,async/awaitBabel 需要重新排列代码,以便我们可以在函数执行期间跟踪我们的位置,并且AsyncIterator是跟踪该状态的对象。

Babel 6 为您提供了更多选择,让您选择您想要使用的实现。请参阅使用 Babel.js 的 Transpile Async Await 提案?

所以关于你的问题:

  • async/await都是它自己的东西。根据规范,他们必须使用 Promise。特别是你可以await在一个承诺上,当你执行一个async函数时,它会给你一个承诺。
  • 由于async函数被转换为返回 promise 的函数,因此没有直接的方法将其与返回 promise 的非异步函数区分开来。你fooPromise应该看起来更像是这样var fooPromiseFunc = function() {return new Promise(r => setTimeout(r, 1))};fooPromiseFunc并且asyncFunc与黑匣子的预期没有区别。它们都是返回承诺的函数。您想async在运行时区分异步函数和非异步函数的原因是什么?在实践中,它们可以以相同的方式使用,所以我不明白为什么你必须以不同的方式威胁它们。出于调试目的,如果您确实需要确定函数是否已定义async,在 Babel 5 中,您可以使用类似(asyncFunc+"").indexOf('regeneratorRuntime.async') > 0或更准确的正则表达式。但这真的很老套,我不会在调试或研究之外的环境中使用。
于 2016-01-12T11:37:54.263 回答