检测函数是否异步(使用 NodeJS)

Detect whether a function is async (using NodeJS)

提问人:Steven 提问时间:11/16/2023 更新时间:11/17/2023 访问量:39

问:

这在 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+ 规范,因此不分青红皂白地期望一切都是异步的确实会改变代码的功能。thenablePromise.resolvethenable

有谁知道如何同时完成此操作或某种解决方法?

JavaScript 节点.js 异步 async-await

评论

1赞 Bergi 11/16/2023
您使用的是哪个版本的 nodejs?您使用的是转译器吗?
0赞 Bergi 11/16/2023
不要使用 ,它已弃用。请改为打电话。.__proto__Object.getPrototypeOf()
1赞 Bergi 11/16/2023
stackoverflow.com/questions/50102413/...... stackoverflow.com/questions/38508420/...... stackoverflow.com/questions/49060405/......
1赞 T.J. Crowder 11/16/2023
使用 Node.js v20.0.0(以及 v18、v17、v16、v15、v11 和 v10),我没有得到您上面报告的结果。我得到 , , , , , .这是有道理的,因为 Node.js 使用 V8,与 Chromium 浏览器中使用的 JavaScript 引擎相同。我不希望 V8 在这方面在浏览器和 Node.js 中的工作方式有所不同。听起来像是你在转译什么的。'Function''AsyncFunction''AsyncFunction'falsefalsefalse
1赞 Amit Mohanty 11/16/2023
这回答了你的问题吗?如何知道函数是否异步?

答:

1赞 Bergi 11/16/2023 #1

我想区分这一点,这样我就可以在保持函数的“签名”的同时不加选择地添加包装器代码

那么你就不应该关心函数是否是使用 / 语法定义的。asyncawait

当你调用它时,你应该关心它是否返回一个承诺。这很容易区分

评论

0赞 Steven 11/17/2023
由于转译器(或编译器,我不知道该怎么称呼它)使用 Promises/A+ 规范,它会破坏当前线程,当我希望某些同步代码继续执行时,这是不可取的。
1赞 T.J. Crowder 11/17/2023
@Steven - 函数是否以其他方式使用/或返回 promise(或其他 thanable)并不重要。重要的是它是否返回一个承诺(嗯,一个 thenable)。上面 Bergi 给出的链接完全符合您在答案中所做的工作——寻找一种方法。asyncawaitthen
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
这基本上就是贝尔吉在他的回答中所说的。他甚至指出了之前关于如何检测可检测的答案。