如何知道一个函数是否异步? [英] How to know if a function is async?
问题描述
我必须将一个函数传递给另一个函数,并将其作为回调执行.问题是有时此函数是异步的,例如:
I have to pass a function to another function, and execute it as a callback. The problem is that sometimes this function is async, like:
async function() {
// Some async actions
}
所以我要根据接收的函数类型执行await callback()
或callback()
.
So I want to execute await callback()
or callback()
depending on the type of function that it is receiving.
有没有办法知道函数的类型?
Is there a way to know the type of the function??
推荐答案
Native async
functions may be identifiable when being converted to strings:
asyncFn[Symbol.toStringTag] === 'AsyncFunction'
或通过 AsyncFunction
构造函数:
Or by AsyncFunction
constructor:
const AsyncFunction = (async () => {}).constructor;
asyncFn instanceof AsyncFunction === true
这不适用于Babel/TypeScript输出,因为asyncFn
是已编译代码中的常规函数,它是Function
或GeneratorFunction
的实例,而不是AsyncFunction
.为确保不会在编译后的代码中为生成器和常规函数提供误报:
This won't work with Babel/TypeScript output, because asyncFn
is regular function in transpiled code, it is an instance of Function
or GeneratorFunction
, not AsyncFunction
. To make sure that it won't give false positives for generator and regular functions in transpiled code:
const AsyncFunction = (async () => {}).constructor;
const GeneratorFunction = (function* () => {}).constructor;
(asyncFn instanceof AsyncFunction && AsyncFunction !== Function && AsyncFunction !== GeneratorFunction) === true
由于本机async
函数于2017年正式引入Node.js,因此该问题可能涉及async
函数的Babel实现,该实现依赖于 transform-regenerator
将生成器转换为常规函数.
Since native async
functions were officially introduced to Node.js in 2017, the question likely refers to Babel implementation of async
function, which relies on transform-async-to-generator
to transpile async
to generator functions, may also use transform-regenerator
to transpile generator to regular functions.
async
函数调用的结果是一个承诺. 根据该提案,承诺或不承诺可能是传递给await
,因此await callback()
是通用的.
The result of async
function call is a promise. According to the proposal, a promise or a non-promise may be passed to await
, so await callback()
is universal.
只有少数情况可能需要这样做.例如,本机async
函数在内部使用本机承诺,并且如果更改了其实现,则不会选择全局Promise
:
There are only few edge cases when this may be needed. For instance, native async
functions use native promises internally and don't pick up global Promise
if its implementation was changed:
let NativePromise = Promise;
Promise = CustomPromiseImplementation;
Promise.resolve() instanceof Promise === true
(async () => {})() instanceof Promise === false;
(async () => {})() instanceof NativePromise === true;
这可能会影响函数的行为(这是 Angular和Zone.js承诺实现的已知问题).即使那样,最好还是检测出不希望有函数返回值的Promise
实例,而不是检测出函数是async
的原因,因为相同的问题适用于使用替代promise实现的任何函数,而不仅仅是async
(解决方案所说的Angular问题是用Promise.resolve
包装async
返回值).
This may affect function behaviour (this is a known problem for Angular and Zone.js promise implementation). Even then it's preferable to detect that function return value is not expected Promise
instance instead of detecting that a function is async
, because the same problem is applicable to any function that uses alternative promise implementation, not just async
(the solution to said Angular problem is to wrap async
return value with Promise.resolve
).
TL; DR:async
函数不应与返回promise的常规函数区分开.没有可靠的方法,也没有理由检测非本机编译的async
函数.
TL;DR: async
functions shouldn't be distinguished from regular functions that return promises. There is no reliable way and no reason to detect non-native transpiled async
functions.
在ES6中,这是通过Promise.resolve
或Promise
构造函数完成的(还处理同步错误):
In ES6, this is done with Promise.resolve
or Promise
constructor (also handles synchronous errors):
Promise.resolve(fnThatPossiblyReturnsAPromise())
.then(result => ...);
new Promise(resolve => resolve(fnThatPossiblyReturnsAPromiseOrThrows()))
.then(result => ...);
在ES2017中,这是通过await
完成的:
In ES2017, this is done with await
:
let result = await fnThatPossiblyReturnsAPromiseOrThrows();
...
这篇关于如何知道一个函数是否异步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!