【问题标题】:How to programmatically find if a function is async?如何以编程方式查找函数是否是异步的?
【发布时间】:2018-08-10 03:41:13
【问题描述】:

我正在尝试覆盖(猴子补丁)Jasmine 框架的 it() 函数,在此过程中,我想知道作为第二个参数传递给 it() 函数的函数是否属于 @ 类型987654323@ 与否。我尝试使用instanceof Promise,因为所有async 函数都返回一个promise,但它永远不会解析为true,并且它永远不会进入以下代码块中的if 块。我尝试将所有函数记录到控制台,发现所有async() 函数规范的返回类型均为tslib_1.awaiter(some args..)

这是我所拥有的:

let newIt = jasmine.getEnv().it;
jasmine.getEnv().it = function(...args): jasmine.Spec {
  // do something.
 if(args[1] instanceOf Promise) {
   debugger; // never comes in here.
   // catch error.
 }
 return newIt.apply(this, arguments);
}

我在这里做错了什么?谁能指出我正确的方向?

谢谢。

编辑:假设我有以下两个虚拟规范,一个是异步的,另一个是同步的:

异步测试:

const exp = () => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(1);
                }, 500);
            });
        };

 it('asyncTest', async () => {
      expect(await exp()).toEqual(1);
  }, 600);

同步:

it('testNon', () => {
     expect(true).toBe(true);
 });

【问题讨论】:

  • 我很好奇,你为什么要这个?
  • 在最新的 Jasmine 中,当您编写异步测试时,它不会正确抛出控制台错误,这有助于我在 Chrome 中进行调试。

标签: javascript typescript jasmine


【解决方案1】:

这是 XY 问题。正如this answer 中所指出的,通常不需要检查它是否是async 函数,因为这无关紧要。 async 函数只是一个返回承诺的函数。 () => Promise.resolve()async () => {} 应该以同样的方式处理。

这可以通过以下事实得到证实:在转译的 TypeScript 代码中无法区分 async 和常规函数 - 它们都只是常规函数。

args[1] instanceOf Promise 不正确,因为函数不是Promise 的实例。 Monkey-patching 通常以这种方式执行(这不是特定于 Jasmine 或这种情况):

let newIt = jasmine.getEnv().it;
jasmine.getEnv().it = function(...args): jasmine.Spec {
  const fn = args[1];
  let newFn;
  if (fn.length > 0) {
    // async spec with done param
    newFn = function (done) {
      const result = fn.call(this, done);
      if(result instanceOf Promise)
      // or even better,
      // if(result && typeof result.then === 'function')
        debugger;
      return result;
    }
  } else {
    newFn = function () {
      const result = fn.call(this);
      if(result instanceOf Promise)
        debugger;          
      return result;
    }
  }

  args[1] = newFn;
  return newIt.apply(this, args);;
}

测试函数 result 应该被检查为 Promise 的一个实例(或者检查它是否可用)。

【讨论】:

  • 非常感谢您清楚地解释它并指出猴子修补的正确方法。奇怪的是,即使是现在,条件也永远不会变为真,也永远不会命中调试器。
  • 抱歉,猴子补丁在那里出错了。更新了代码,猜猜这应该可以解决问题。
  • 很抱歉花了太长时间才接受您的回答。你摇滚。万分感谢。 :)
【解决方案2】:

这不起作用,因为异步函数总是返回一个 Promise,但它们本身并不是 Promise。

简单的答案是查看相关函数的构造函数(但我会解释为什么你不应该这样做):

const isAsync = func.constructor.name === 'AsyncFunction';

这种方法的问题在于,异步函数并不能真正与返回承诺的常规函数​​区分开来。最好使用Promise.resolve 将任何函数调用的结果转换为Promiseawait

【讨论】:

  • 你能给我一个简单的例子吗?我如何在我的情况下实现这个?我已经用几个简单的it 规范更新了我的代码,这些规范可以在场景中使用。
  • 你是说,我应该这样做:let x = Promise.resolve(args[1]); 然后检查if(p instanceof Promise){ // do something} 吗?我不太明白await 部分。
猜你喜欢
  • 2012-01-04
  • 1970-01-01
  • 2011-12-10
  • 2013-05-05
  • 1970-01-01
  • 2016-11-25
  • 2013-10-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多