流星方法 + 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
我正在使用带有 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