如何知道函数是否异步?理论实践
我必须将一个函数传递给另一个函数,并将其作为回调执行。问题是有时这个函数是异步的,比如:
async function() {
// Some async actions
}
因此,我想执行或取决于它正在接收的函数类型。await callback()
callback()
有没有办法知道函数的类型??
我必须将一个函数传递给另一个函数,并将其作为回调执行。问题是有时这个函数是异步的,比如:
async function() {
// Some async actions
}
因此,我想执行或取决于它正在接收的函数类型。await callback()
callback()
有没有办法知道函数的类型??
本机函数在转换为字符串时可以识别:async
asyncFn[Symbol.toStringTag] === 'AsyncFunction'
或者通过异步函数
构造函数:
const AsyncFunction = (async () => {}).constructor;
asyncFn instanceof AsyncFunction === true
这不适用于 Babel/TypeScript 输出,因为它是转译代码中的常规函数,它是 or 的实例,而不是 。要确保它不会在转译代码中为生成器和常规函数提供误报,请执行以下操作:asyncFn
Function
GeneratorFunction
AsyncFunction
const AsyncFunction = (async () => {}).constructor;
const GeneratorFunction = (function* () => {}).constructor;
(asyncFn instanceof AsyncFunction && AsyncFunction !== Function && AsyncFunction !== GeneratorFunction) === true
由于原生函数在2017年被正式引入Node.js,这个问题可能是指函数的Babel实现,它依赖于转换-异步-生成器
来转译到生成器函数,也可能使用变换-再生器
将生成器转译为规则函数。async
async
async
函数调用的结果是一个 promise。根据该提案,承诺或非承诺可以传递给 ,因此是普遍的。async
await
await callback()
只有少数边缘情况可能需要这样做。例如,本机函数在内部使用本机承诺,如果其实现被更改,则不会选择全局函数:async
Promise
let NativePromise = Promise;
Promise = CustomPromiseImplementation;
Promise.resolve() instanceof Promise === true
(async () => {})() instanceof Promise === false;
(async () => {})() instanceof NativePromise === true;
这可能会影响函数行为(这是 Angular 和 Zone 的已知问题.js promise 实现)。即使这样,最好检测函数返回值不是预期的实例,而不是检测函数是,因为同样的问题适用于任何使用替代 promise 实现的函数,而不仅仅是(所述 Angular 问题的解决方案是用 ) 包装返回值)。Promise
async
async
async
Promise.resolve
从外部看,函数只是一个无条件返回本机 promise 的函数,因此它应该被视为一个函数。即使一个函数曾经被定义过,它也可以在某个时刻被转译并成为正则函数。async
async
在ES6中,可能返回承诺的函数可以与(允许同步错误)或包装构造函数(处理同步错误)一起使用:Promise.resolve
Promise
Promise.resolve(fnThatPossiblyReturnsAPromise())
.then(result => ...);
new Promise(resolve => resolve(fnThatPossiblyReturnsAPromiseOrThrows()))
.then(result => ...);
在ES2017中,这是通过以下方式完成的(这是问题中的示例应该如何编写的):await
let result = await fnThatPossiblyReturnsAPromiseOrThrows();
...
检查一个对象是否是一个承诺是一个单独的问题,但通常它不应该太严格或松散,以覆盖角落案例。 如果全局被替换,则可能不起作用。当 Angular 和非 Angular 应用程序接口时,可能会发生这种情况。instanceof Promise
Promise
Promise !== (async () => {})().constructor
需要的函数,即始终返回 promise 的函数应该首先被调用,然后检查返回的值是一个 promise:async
let promise = fnThatShouldReturnAPromise();
if (promise && typeof promise.then === 'function' && promise[Symbol.toStringTag] === 'Promise') {
// is compliant native promise implementation
} else {
throw new Error('async function expected');
}
TL;DR:异步
函数不应与返回 promise 的常规函数区分开来。没有可靠的方法,也没有实际理由来检测非本机转译的异步
函数。
只要只使用本机异步函数(通常是这种情况),我更喜欢这种简单的方法:
theFunc.constructor.name == 'AsyncFunction'