我试图更好地了解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
只是兼容有承诺?
并且,有没有办法在运行时区分简单的function
和async function
(以Babel兼容的方式)?
答案 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))};
,使fooPromiseFunc
和asyncFunc
与黑匣子无法区分。它们都是回报承诺的功能。你想在运行时区分async
和无异步函数的原因是什么?在实践中,它们可以以相同的方式使用,所以我不明白为什么你必须以不同的方式威胁它们。出于调试目的,如果您确实需要确定函数是否已定义async
,则在Babel 5中您可以使用(asyncFunc+"").indexOf('regeneratorRuntime.async') >
0
或更准确的正则表达式。但那确实是
hacky,我不会在调试或学习之外的上下文中使用。