如何判断Javascript函数是否是Async函数
判断Javascript函数是否是Async函数有好几种方法:
- 调用
Object.prototype.toString.call(async function(){})
,如果返回[object AsyncFunction]
,则说明是Async函数。 -
简单地调用
asyncFn.toString()
async function myAsyncFunc(){} myAsyncFunc.toString() // 结果="async function myAsyncFunc(){}"
asyncFn.toString()
直接返回函数定义字符,只要判断是否以async开头
即可。
以上算是比较标准的方法,在原生支持ES6/7/8以下的浏览器中是没有问题的,但是在启用了Babel转码
后就无效
了。比如在Babel7
中, async function myAsyncFunc(){}
会被转码成:
function myAsyncFunc() {
....
return _regenerator.default.async(function myAsyncFunc$(_context) {
.....
}
}
因此,如果还是用上述方法就无效了。因为被Babel转码后,所有的async均被转成普通的函数。
例如在React Native
环境就启用了Babel转码,调用Object.prototype.toString.call(async function(){})
,如果返回的是[Object Function]
。
由于在很多场景下我们会启用Babel
转码.因此,判断是否是Async
函数,需要考虑此情况。
基本方法就是通过asyncFunc.toString()
获取到函数内容,判断Babel
转码后的async
函数特征即可。
export function isAsyncFunction(fn){
let fnStr =fn.toString()
return Object.prototype.toString.call(fn) === '[object AsyncFunction]' || fnStr.includes("return _regenerator.default.async(function")
}
需要注意的是,async函数经Babel 5/6/7
经转码后生成的代码,在不同的版本下可能是不一样的,甚至也不排除未来Babel 8
转码的结果也会发生变化。因此,此方法并不一定可靠,有谁知道更加标准通用的方法可以告知一下。
由于Babel转码的情况存在,因此像判断一个对象是否是Class的函数,也存在类似因Babel转码导致的问题。例如:
function isClass(obj){
if (typeof(cls) === 'function' && cls.prototype) {
try {
cls.arguments && cls.caller;
} catch(e) {
return true;
}
}
return false;
}
以上函数在经Babel转码的情况下是无效的,如果适应Babel转码的情况,也一样要进行处理。