Javascript node.js使用function.prototype.apply执行通用函数
我有一系列的行动方法,例如:Javascript node.js使用function.prototype.apply执行通用函数,javascript,node.js,Javascript,Node.js,我有一系列的行动方法,例如: function doA(x, y, callback){ .. some additional logic here ... do_something_async(x, y, function(result) { callback(result); }); } function doB(x, y, z, callback){ .. some additional logic here ... do_something_async
function doA(x, y, callback){
.. some additional logic here ...
do_something_async(x, y, function(result) {
callback(result);
});
}
function doB(x, y, z, callback){
.. some additional logic here ...
do_something_async2(x, y, z, function(result) {
callback(result);
});
}
我想创建一个通用执行函数,例如:
function doCommand(fn) {
// Execute the fn function here with the arguments
// Do something with the result to the callback from the action function
// (which may require running the action function again...)
}
函数docomand
将作为第一个参数接收操作命令的名称,其余参数将根据操作命令的要求。换言之:
docomand(doA,5,10,cbfn)
将使用相关参数调用doA
。而docomand(doB,1,2,3,cbfn)
将使用相关参数调用doB
到目前为止,我的docomand
函数如下所示:
function doCommand(fn) {
fn.apply(null, arguments);
}
但是,我不知道如何在执行异步函数后在doCommand
内捕获result的值,因为基于此值,我可能还需要执行其他操作,例如,再次运行action函数。
另外,这需要更改每个操作命令的签名,以忽略由apply
函数创建的第一个null
参数
我很确定有一种更聪明的方法可以做到这一点。如果你能帮我找到方法,我将不胜感激
谢谢
编辑:
典型的操作函数如下所示:
function doA(arg1, arg2, cb) {
... some logic using arguments ...
asyncmodule.once('event', function(event) {
... do something ...
callback(event.result);
});
asyncmodule.send('A command', [list of specific arguments]);
}
动作函数的调用方需要对结果进行处理,但是对于指定的失败结果,需要重复或更改参数,然后重试。除非您有一种实用的方法来确定哪个参数是回调函数,否则我看不到一种好的方法 然而,在另一个地方,使用承诺而不是回调将使异步任务变得更简单。如果异步函数使用承诺而不是回调,则可以执行以下操作:
function doA(x, y){
return do_something_with_promises(x, y);
}
function doB(x, y, z){
return do_something_with_promises2(x, y, z);
}
function doCommand(fn) {
var args = Array.prototype.slice.call(arguments, 1);
return fn.apply(null, args)
.then(function (result) {
if (result === "run me again!") {
return fn.apply(null, args);
}
});
}
doCommand(doA, "Hey!", "Hey!")
.then(function (result) {
// ...
});
回调函数是函数的最终参数,这是一个非常强大的约定,所以我假设您正在使用它。我们将首先修复参数并注入我们自己的回调函数,然后我们可以调用函数并开始我们的工作
function doCommand(fn) {
var args = Array.prototype.slice.call(arguments); // We want a real array
args = args.slice(1); // Otherwise it contains fn, which isn't right
var finalCallback = args[args.length - 1]; // We'll need this at the end
args = args.slice(0, -1); // But we don't need it now
fn.apply(null, args.concat( function() { // This looks weird, but it allows us
// to keep the callback inline with
// the function call
// Here you can operate on the results
}));
}
请注意,concat
是非破坏性的,因此您可以通过不同的回调调用fn
。别忘了最终打电话给finalCallback
正如Bergi所指出的,你可以把所有的片段组合起来——我只是把它们分开,以便更好地对它们进行评论:
var args = Array.prototype.slice.call(arguments, 1, -1)
当然,您必须从
参数中提取finalCallback
,而不是args
。您可以在调用docomand
的地方直接调用fn
吗?问题是,如果结果中有特定值,我需要对所有操作函数执行相同的操作。我不想每次调用action函数后都编写它。我有大约50个具有不同签名的不同操作函数。正如我在OP中所说的,我可能需要根据结果的值再次执行操作函数(或者可能不止一次并输入其他逻辑)。事实上,你不需要匿名函数表达式,所以doA=do\u something\u async
和doB=do\u something\u async2
就足够了。@Bergi,我不能替换动作函数。在这些函数中有更多的逻辑。为了便于讨论,我简化了它。我会在OP中更正它以避免混淆。嗯,谢谢@JLRishe的快速响应。我现在的应用程序基本上是基于async.js的异步执行,所以我不确定现在是否可以切换到Promissions。但我可能需要考虑一下。这就是我一直在寻找的!测试它,它的工作。美丽的谢谢@Aaron!!最好使用切片
而不是数组。应用
,即使您不打算将一个(单个)数字作为第一个参数。@Bergi我看到它是双向的。为什么选择slice
?正如我所说的,因为Array.apply(null,[5])
不起作用。当然,通过执行var args=Array.prototype.slice.call(arguments,1,-1)
:-)您可以在这里保存很多行。是的,这些片段肯定可以组合在一起,但我希望能够分别对它们进行注释。我本想在最后记下来的,但忘了。