流星方法 + check() + audit-argument-checks + async/await 导致异常

Meteor method + check() + audit-argument-checks + async/await causes exception

我正在使用带有 check() 和 audit-check-arguments 包的流星。

当我使用流星方法使用async/await并传递一个参数时,即使我使用check()来验证函数参数,审计包仍然抛出一个异常表明不是所有的输入参数都已经过检查。如果我删除 async/await 实现,则包不会 crib。我错过了什么?

示例:

Meteor.methods({

    test: async function(param1){
          check(param1, String);
          ...
          await ....
    }
});

抛出异常:

=> Client modified -- refreshing
I20200513-10:43:27.978(5.5)? Exception while invoking method 'test' Error: Did not check() all arguments during call to 'test'
I20200513-10:43:27.979(5.5)?     at ArgumentChecker.throwUnlessAllArgumentsHaveBeenChecked (packages/check/match.js:515:13)

而这种传统的流星方法不会抛出任何异常

Meteor.methods({

    test:  function(param1){
          check(param1, String);
          ...

    }
});

我确定我只传递了一个参数。

看起来 audit-argument-checks 只适用于同步函数。

我没有这个问题,因为我们使用 mdg:validated-method,它要求您为每个方法指定一个参数验证器。

它通过用这个包装方法函数来关闭参数检查器:

    // Silence audit-argument-checks since arguments are always checked when using this package
    check(args, Match.Any);

我能想到的最简单的解决方案是将检查与异步函数分开。您可以使用包装函数来执行此操作:

function checkAndRun(check, run) {
  return function(...args) {
    check.apply(this, args);
    return run.apply(this, args);
  }
}

Meteor.methods({
  'example': checkAndRun(
    function(exampleID){
      check(exampleID, String);
    },
    async function(exampleID) {
      const result = await doSomethingAsync(exampleID);
      SomeDB.update({ _id: exampleID }, { $set: { someKey: result.value } });
      return result.status;
    }
  }
});

或者您甚至可以使用异步 IIFE 内联:

Meteor.methods({
  example(exampleID) {
    check(exampleID, String);
    return (async () => {
      const result = await doSomethingAsync(exampleID);
      SomeDB.update({ _id: exampleID }, { $set: { someKey: result.value } });
      return result.status;
    })()
  }
});

仔细想想,这比我最初想到的最简单的解决方案要简单得多

您只是想以某种方式将同步检查与异步方法主体分开


如果您好奇,请深入了解源代码以查看它的调用位置。当调用该方法时(在 ddp-server/livedata-server 中),我们在这里结束,对 audit-argument-checks 的第一个引用的同步方法调用: https://github.com/meteor/meteor/blob/master/packages/ddp-server/livedata_server.js#L1767-L1770

这将我们带到 check/Match 以在此处进行另一个同步调用:https://github.com/meteor/meteor/blob/71f67d9dbac34aba34ceef733b2b51c2bd44b665/packages/check/match.js#L114-L123

它使用了奇怪的 Meteor.EnvironmentVariable 构造,它在幕后有另一个同步调用:https://github.com/meteor/meteor/blob/master/packages/meteor/dynamics_nodejs.js#L57