ES7异步功能和承诺之间的技术差异?

时间:2016-01-12 09:30:46

标签: javascript babeljs ecmascript-next

我试图更好地了解JavaScript中的async function技术,即使我基本上知道如何使用它们。

async / await的许多介绍都相信async函数基本上只是一个承诺,但事实并非如此(至少不是Babel6-transpiled code):

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兼容的方式)?

2 个答案:

答案 0 :(得分:10)

异步函数是一个返回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循环这样的常规工具来处理它们,即使它们是异步的。

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

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

我不熟悉在运行时区分这两者的方法,因为像类一样,异步函数只是Promises之上的糖。 (尽管可能存在使用函数.toString并解析结果的黑客攻击,但我不算这些。)

答案 1 :(得分:0)

这对夫妇async/await是一种让您以同步方式编写异步代码的机制,而且我认为它是迄今为止处理异步代码的最简单易读的语法(另请参阅{{3} })。语法的强大之处在于await的工作原理。但是为了在函数体内使用await,函数必须以async为前缀。

如果您需要更多信息,可以使用this article

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

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

如果你深入挖掘Babel的babel-regenerator-runtime套餐,你会发现Facebook的代码。在transpiled code您会找到:

// 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/await Babel需要重新排列代码,以便我们可以跟踪我们在执行函数期间的位置,AsyncIterator是跟踪的对象那个州。

Babel 6为您提供了更多选项,让您选择要使用的实现。见line 205

关于你的问题:

  • async/await都属于它自己。根据规范,他们必须与承诺一起工作。特别是你可以await承诺,当你执行async函数时,它会给你一个承诺。
  • 由于async函数被转换为返回promise的函数,因此没有一种直接的方法可以将它与返回promise的无异步函数区分开来。 您的fooPromise应该更像var fooPromiseFunc = function() {return new Promise(r => setTimeout(r, 1))};,使fooPromiseFuncasyncFunc与黑匣子无法区分。它们都是回报承诺的功能。你想在运行时区分async和无异步函数的原因是什么?在实践中,它们可以以相同的方式使用,所以我不明白为什么你必须以不同的方式威胁它们。出于调试目的,如果您确实需要确定函数是否已定义async,则在Babel 5中您可以使用(asyncFunc+"").indexOf('regeneratorRuntime.async') > 0或更准确的正则表达式。但那确实是 hacky,我不会在调试或学习之外的上下文中使用。