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)
:-)您可以在这里保存很多行。是的,这些片段肯定可以组合在一起,但我希望能够分别对它们进行注释。我本想在最后记下来的,但忘了。