提问人:Steven 提问时间:11/16/2023 更新时间:11/17/2023 访问量:39
检测函数是否异步(使用 NodeJS)
Detect whether a function is async (using NodeJS)
问:
这在 Web 浏览器中是一个简单的任务,但在 NodeJS 中,它没有区别:
console.log({
// 'Function' in browser, but empty string ('') in NodeJS
'(() => {}).constructor.name': (() => {}).constructor.name,
'(() => {}).__proto__.constructor.name': (async () => {}).__proto__.constructor.name,
// 'AsyncFunction' in browser, but empty string ('') in NodeJS
'(async () => {}).constructor.name': (async () => {}).constructor.name,
'(async () => {}).__proto__.constructor.name': (async () => {}).__proto__.constructor.name,
// Evaluates to false in browser, but true in NodeJS
'(async () => {}).constructor === (() => {}).constructor': (async () => {}).constructor === (() => {}).constructor,
'(async () => {}).__proto__ === (() => {}).__proto__': (async () => {}).__proto__ === (() => {}).__proto__,
'(async () => {}).__proto__.constructor === (() => {}).__proto__.constructor': (async () => {}).__proto__.constructor === (() => {}).__proto__.constructor,
});
我想要区分这一点的原因是,我可以不加选择地添加包装器代码,同时保持函数的“签名”。如果我要将所有内容转换为仅接受一个对象,那么我将不得不将大多数函数调用转换为异步方法(或期望异步)。这对 nodejs(或 React Native)来说是一个问题,因为它执行了 Promises/A+ 规范,因此不分青红皂白地期望一切都是异步的确实会改变代码的功能。thenable
Promise.resolve
thenable
有谁知道如何同时完成此操作或某种解决方法?
答:
1赞
Bergi
11/16/2023
#1
我想区分这一点,这样我就可以在保持函数的“签名”的同时不加选择地添加包装器代码
那么你就不应该关心函数是否是使用 / 语法定义的。async
await
当你调用它时,你应该关心它是否返回一个承诺。这很容易区分。
评论
0赞
Steven
11/17/2023
由于转译器(或编译器,我不知道该怎么称呼它)使用 Promises/A+ 规范,它会破坏当前线程,当我希望某些同步代码继续执行时,这是不可取的。
1赞
T.J. Crowder
11/17/2023
@Steven - 函数是否以其他方式使用/或返回 promise(或其他 thanable)并不重要。重要的是它是否返回一个承诺(嗯,一个 thenable)。上面 Bergi 给出的链接完全符合您在答案中所做的工作——寻找一种方法。async
await
then
0赞
Steven
11/17/2023
#2
我的临时解决方法是测试结果是否为 a 并返回一个等待结果的异步匿名函数。thenable
const debug = (message, fn) => {
const reportError = (e, isSync) => {
console.error(`${message}: ${e.message || e} (${isSync})`);
throw e;
};
return (...args) => {
try {
// First, attempt to execute the provided function as if it is synchronous
const result = fn?.(...args);
// If its result is a thenable, then catch any errors while awaiting its response
if (typeof result?.then === 'function') {
return (async () => {
try {
return await result;
}
catch (e) { reportError(e, false); }
})();
}
return result;
}
catch (e) { reportError(e, true); }
};
};
感觉它应该可以进一步减少,但需要等待结果(我相信?)才能抓住被拒绝的承诺。
编辑:因为我在我的 React Native 项目中使用 TypeScript,所以它正在转译代码,使异步函数看起来就像同步函数一样。
评论
1赞
T.J. Crowder
11/17/2023
这基本上就是贝尔吉在他的回答中所说的。他甚至指出了之前关于如何检测可检测的答案。
评论
.__proto__
Object.getPrototypeOf()
'Function'
'AsyncFunction'
'AsyncFunction'
false
false
false