ES7 异步函数和承诺之间的技术区别?
technical difference between ES7 async function and a promise?
我试图更好地理解 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
只是兼容 与承诺?
并且,有没有办法在运行时(以 Babel 兼容的方式)区分简单的 function
和 async function
?
异步函数是 函数,returns 承诺。它可以帮助您解决一系列异步操作接连发生的情况:
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 循环来处理它们,即使它们是异步的。
异步函数不是 promises 的替代品,它们是它们之上的糖分,用于处理具有许多顺序异步操作的特定情况。
因为 await
基本上只是 "await for this promise",你仍然可以使用像 Promise.all()
和 Promise.race()
这样的酷聚合方法并等待几个(或几个)承诺中的第一个。
我不熟悉在运行时区分两者的方法,因为与 类 一样,异步函数只是 Promises 之上的糖分。 (虽然可能会有像使用函数的 .toString
和解析结果这样的黑客攻击,但我不计算那些)。
这对 async/await
是一种让您以同步方式编写异步代码的机制,在我看来,这是迄今为止处理异步代码最简单易读的语法(另请参阅 this article).语法的强大之处在于 await
的工作原理。但是为了在函数体内使用 await
,函数必须有前缀 async
。
如果您需要更多信息,请查看 spec for async/await
here。
Babel 5 中的当前实现是基于https://github.com/facebook/regenerator. As you can see in the transpiled code 函数被编译为:
function asyncFunc(which, one, two) {
return regeneratorRuntime.async(function asyncFuncMaybe$(context[=10=]) {
...
如果你深入挖掘 Babel 的 babel-regenerator-runtime
包,你会找到 Facebook 的代码。在 line 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/await
Babel 需要重新排列代码,这样我们就可以在函数执行期间跟踪我们的位置,而 AsyncIterator
是保持的对象该状态的轨迹。
Babel 6 给了你更多的选择,让你选择你想使用的实现。参见
所以关于你的问题:
async/await
都是它自己的东西。根据规范,他们必须与承诺一起工作。特别是你可以 await
一个承诺,当你执行一个 async
函数时,它会 return 你一个承诺。
- 由于
async
函数被转译为 return promise 的函数,因此没有直接的方法将其与 return 的 no-async 函数区分开来承诺。
您的 fooPromise
应该看起来更像 var fooPromiseFunc = function() {return new Promise(r => setTimeout(r, 1))};
,这使得 fooPromiseFunc
和 asyncFunc
与黑盒预期无法区分。它们都是 return 承诺的功能。为什么要在运行时区分 async
和 no-async 函数?实际上,它们可以以相同的方式使用,所以我不明白为什么你必须以不同的方式威胁它们。出于调试目的,如果你真的需要找出一个函数是否定义了 async
,在 Babel 5 中你可以使用类似 (asyncFunc+"").indexOf('regeneratorRuntime.async') >
0
的东西或更准确的正则表达式。但那是真的
hacky,我不会在调试或研究之外的上下文中使用。
我试图更好地理解 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
只是兼容 与承诺?并且,有没有办法在运行时(以 Babel 兼容的方式)区分简单的
function
和async function
?
异步函数是 函数,returns 承诺。它可以帮助您解决一系列异步操作接连发生的情况:
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 循环来处理它们,即使它们是异步的。
异步函数不是 promises 的替代品,它们是它们之上的糖分,用于处理具有许多顺序异步操作的特定情况。
因为 await
基本上只是 "await for this promise",你仍然可以使用像 Promise.all()
和 Promise.race()
这样的酷聚合方法并等待几个(或几个)承诺中的第一个。
我不熟悉在运行时区分两者的方法,因为与 类 一样,异步函数只是 Promises 之上的糖分。 (虽然可能会有像使用函数的 .toString
和解析结果这样的黑客攻击,但我不计算那些)。
这对 async/await
是一种让您以同步方式编写异步代码的机制,在我看来,这是迄今为止处理异步代码最简单易读的语法(另请参阅 this article).语法的强大之处在于 await
的工作原理。但是为了在函数体内使用 await
,函数必须有前缀 async
。
如果您需要更多信息,请查看 spec for async/await
here。
Babel 5 中的当前实现是基于https://github.com/facebook/regenerator. As you can see in the transpiled code 函数被编译为:
function asyncFunc(which, one, two) {
return regeneratorRuntime.async(function asyncFuncMaybe$(context[=10=]) {
...
如果你深入挖掘 Babel 的 babel-regenerator-runtime
包,你会找到 Facebook 的代码。在 line 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/await
Babel 需要重新排列代码,这样我们就可以在函数执行期间跟踪我们的位置,而 AsyncIterator
是保持的对象该状态的轨迹。
Babel 6 给了你更多的选择,让你选择你想使用的实现。参见
所以关于你的问题:
async/await
都是它自己的东西。根据规范,他们必须与承诺一起工作。特别是你可以await
一个承诺,当你执行一个async
函数时,它会 return 你一个承诺。- 由于
async
函数被转译为 return promise 的函数,因此没有直接的方法将其与 return 的 no-async 函数区分开来承诺。 您的fooPromise
应该看起来更像var fooPromiseFunc = function() {return new Promise(r => setTimeout(r, 1))};
,这使得fooPromiseFunc
和asyncFunc
与黑盒预期无法区分。它们都是 return 承诺的功能。为什么要在运行时区分async
和 no-async 函数?实际上,它们可以以相同的方式使用,所以我不明白为什么你必须以不同的方式威胁它们。出于调试目的,如果你真的需要找出一个函数是否定义了async
,在 Babel 5 中你可以使用类似(asyncFunc+"").indexOf('regeneratorRuntime.async') > 0
的东西或更准确的正则表达式。但那是真的 hacky,我不会在调试或研究之外的上下文中使用。