Fac*_*teo 58 javascript node.js async-await ecmascript-next
我必须将一个函数传递给另一个函数,并将其作为回调执行.问题是有时这个函数是异步的,比如:
async function() {
// Some async actions
}
Run Code Online (Sandbox Code Playgroud)
所以我想执行await callback()
或callback()
取决于它接收的函数类型.
有没有办法知道函数的类型?
Est*_*ask 46
转换为字符串时,本机async
函数可能是可识别的:
asyncFn[Symbol.toStringTag] === 'AsyncFunction'
Run Code Online (Sandbox Code Playgroud)
或者由AsyncFunction
构造函数:
const AsyncFunction = (async () => {}).constructor;
asyncFn instanceof AsyncFunction === true
Run Code Online (Sandbox Code Playgroud)
这不适用于Babel/TypeScript输出,因为asyncFn
在转换代码中是常规函数,它是Function
or 的实例GeneratorFunction
,而不是AsyncFunction
.为了确保它不会对转换代码中的生成器和常规函数给出误报:
const AsyncFunction = (async () => {}).constructor;
const GeneratorFunction = (function* () => {}).constructor;
(asyncFn instanceof AsyncFunction && AsyncFunction !== Function && AsyncFunction !== GeneratorFunction) === true
Run Code Online (Sandbox Code Playgroud)
问题显然是指Babel实现的async
功能,它依赖于transform-async-to-generator
转换async
为生成器功能,也可以用于transform-regenerator
将生成器转换为常规功能.
async
函数调用的结果是一个承诺.根据该提议,可以传递承诺或不承诺await
,因此await callback()
是普遍的.
只有少数边缘情况可能需要.例如,本机async
函数在内部使用本机promise,Promise
如果其实现发生更改,则不会获取全局:
let NativePromise = Promise;
Promise = CustomPromiseImplementation;
Promise.resolve() instanceof Promise === true
(async () => {})() instanceof Promise === false;
(async () => {})() instanceof NativePromise === true;
Run Code Online (Sandbox Code Playgroud)
这可能会影响函数行为(这是Angular和Zone.js承诺实现的已知问题).即便如此,最好检测函数返回值不是预期的Promise
实例而不是检测函数async
,因为同样的问题适用于使用替代promise实现的任何函数,而不仅仅是async
(所述Angular问题的解决方案是包装async
返回价值与Promise.resolve
).
TL; DR:async
函数不应与返回promise的常规函数区分开来.在这种情况下,他们当然不应该被区分.没有可靠的方法也没有理由去检测非原生的转换async
函数.
Cha*_*ira 19
@rnd和@estus都是正确的.
但是,在这里用一个实际的工作解决方案来回答这个问题
function isAsync (func) {
const string = func.toString().trim();
return !!(
// native
string.match(/^async /) ||
// babel (this may change, but hey...)
string.match(/return _ref[^\.]*\.apply/)
// insert your other dirty transpiler check
// there are other more complex situations that maybe require you to check the return line for a *promise*
);
}
Run Code Online (Sandbox Code Playgroud)
这是一个非常有效的问题,我很沮丧,有人拒绝投票给他.此类检查的主要用例是库/框架/装饰器.
这些都是早期的,我们不应该低估有效问题.
Ale*_*der 16
我更喜欢这种简单的方式:
theFunc.constructor.name == 'AsyncFunction'
Run Code Online (Sandbox Code Playgroud)
gyo*_*gyo 14
似乎await
也可以用于正常功能。我不确定这是否可以被视为“良好实践”,但它是:
async function asyncFn() {
// await for some async stuff
return 'hello from asyncFn'
}
function syncFn() {
return 'hello from syncFn'
}
async function run() {
console.log(await asyncFn()) // 'hello from asyncFn'
console.log(await syncFn()) // 'hello from syncFn'
}
run()
Run Code Online (Sandbox Code Playgroud)
以下是 David Walsh 在他的博文中提供的一个简短而有用的方法:
const isAsync = myFunction.constructor.name === "AsyncFunction";
Run Code Online (Sandbox Code Playgroud)
干杯!
如果您使用的是NodeJS 10.x或更高版本
使用本机util函数。
util.types.isAsyncFunction(function foo() {}); // Returns false
util.types.isAsyncFunction(async function foo() {}); // Returns true
Run Code Online (Sandbox Code Playgroud)
不过,请不要忘记回答所有问题。刚偶然返回一个承诺的函数将返回一个假负数。
最重要的是(来自文档):
请注意,这只会报告JavaScript引擎正在显示的内容。特别是,如果使用了编译工具,则返回值可能与原始源代码不匹配。
但是,如果您async
在NodeJS 10中使用并且没有进行转换。这是一个很好的解决方案。
归档时间: |
|
查看次数: |
12503 次 |
最近记录: |