在JavaScript中,如何从函数数组中执行下一个函数

时间:2018-08-13 12:34:47

标签: javascript node.js

我有一系列函数,如:

funcArray = [func1, func2, func3];

在给定函数中,我要在数组中执行下一个函数。我该怎么做呢?这是我的基本骨架:

function func1() {
  // I get current function caller
  var currentFunc = func1.caller;

  // I want to execute the next function. Happens to be func2 in the example.

}

我不能使用indexOf函数,就像字符串或数字数组一样。 注意:此问题似乎类似于this及其所指的问题。但是,这是一个不同的问题。

我想仅通过修改数组来更改处理顺序。这就是目标。可能会更有效的方法。

说明:基于一些评论: funcArray是全局的。

目标是以简单高效的方式为Node.js HTTP模块实现中间件,而无需使用任何第三方模块。

5 个答案:

答案 0 :(得分:32)

除非func1关闭funcArray,否则您不能伸出手来找到func2并执行它,也应该这样做。即使func1 确实funcArray结束,func1的关注点分离仍很差,funcArray会伸出手并在func2中找到自己执行funcArray.forEach(fn => fn());

相反,还有其他代码负责运行这些功能。

如果它们是同步的

如果这些函数同步完成其工作,则只需:

for (const fn of funcArray) {
    fn();
}

reduce

或者如果一个函数的结果应该传递给下一个,则可以使用const finalResult = funcArray.reduce((previousResult, fn) => fn(previousResult), undefined);

undefined

...其中func1是要传递给reduce的值。

如果它们是异步的

如果他们没有同步完成工作,则需要向他们提供一种方法,以通知呼叫者他们已经完成工作。承诺是一种很好的标准方法,但是您可以使用简单的回调。

例如,如果让它们返回承诺,则可以使用旧的承诺funcArray.reduce((p, fn) => { return p.then(() => { fn(); }); }, Promise.resolve()); 技巧:

funcArray.reduce((p, fn) => {
    return p.then(fn);
}, Promise.resolve());

或者是否将一个函数的结果传递给下一个:

Promise.resolve

您可以为func1提供一个参数,以设置要传递给undefined的值(如果没有,它将接收window.onpopstate)。

答案 1 :(得分:4)

您可以将函数在数组中的索引绑定到该函数,以便可以使用此索引来获取并调用下一个函数:

var funcArray = [func1, func2];
var boundFuncArray = funcArray.map((f, i) => f.bind(null, i));

boundFuncArray[0](); 

function func1(nextFunctionIndex) {
    console.log('func1 called');
    // Execute next function:
    var nextFunc = boundFuncArray[nextFunctionIndex + 1];
    nextFunc && nextFunc();
}

function func2(nextFunctionIndex) {
    console.log('func2 called');
    // Execute next function:
    var nextFunc = boundFuncArray[nextFunctionIndex + 1];
    nextFunc && nextFunc();
}

正如T.J Crowder在下面的评论中所述,您还可以将下一个函数绑定到当前函数:

var funcArray = [func1, func2];
var boundFuncArray= funcArray.map((f, i, arr) => f.bind(null, arr[i + 1]));

boundFuncArray[0](); 

function func1(nextFunc) {
    console.log('func1 called');
    // Execute next function:
    nextFunc && nextFunc();
}

function func2(nextFunc ) {
    console.log('func2 called');
    // Execute next function:
    nextFunc && nextFunc();
}

答案 2 :(得分:3)

您可以使用arguments.callee.name获取当前函数的名称,循环遍历函数数组,然后调用下一个函数:

funcArray = [func1, func2, func3];

// Only func1() and func2() will be documented since the others have repeating code

function func1() {
    // show the current function name
    console.log(arguments.callee.name);

    // loop the array of functions
    for(var i = 0; i < funcArray.length; ++i)
    {
        // when the current array item is our current function name and
        // another function exists after this then call it and break
        if(funcArray[i] === arguments.callee && funcArray[i+1])
        {
            funcArray[i+1]();
            break;
        }
    }
}

function func2() {
    console.log(arguments.callee.name);
    
    // some logic which switches our next function to be func4()
    funcArray[2] = func4;
    
    for(var i = 0; i < funcArray.length; ++i)
    {
        if(funcArray[i] === arguments.callee && funcArray[i+1])
        {
            funcArray[i+1]();
            break;
        }
    }
}

function func3() {
    console.log(arguments.callee.name);
    for(var i = 0; i < funcArray.length; ++i)
    {
        if(funcArray[i] === arguments.callee && funcArray[i+1])
        {
            funcArray[i+1]();
            break;
        }
    }
}

function func4() {
    console.log(arguments.callee.name);
    for(var i = 0; i < funcArray.length; ++i)
    {
        if(funcArray[i] === arguments.callee && funcArray[i+1])
        {
            funcArray[i+1]();
            break;
        }
    }
}

// call the first function
funcArray[0]();

输出:

func1
func2
func4

答案 3 :(得分:0)

我不知道您的函数是否需要某些参数,但这是我想到的第一件事。

var functArray = [
  function() {
    console.log("function1 executed");
  },
   function() {
    console.log("function2 executed");
  },
    function() {
    console.log("function3 executed");
  },
    function() {
    console.log("function4 executed");
  }];
  
  functArray.forEach(function(x){
    x();
  });

答案 4 :(得分:0)

接受的答案和其他评论确实对我有所帮助,但是我的实现方式如下:

//The functions are defined as variables. 
//They do not get hoisted, so must be defined first.
func1 = function (arg1, arg2) {
  //Code to do whatever...
  ...
  //Execute the next function. 
  //The name of the function is returned by executing nextFunc()
  global[nextFunc()](arg1, arg2, arg3);

}
func2 = function (arg1)  { //Note different type of args
  ...
}

//Note that this is an array of strings representing function names.
funcArray = ["func1", "func2", "func3",...]

//Start the execution...
func1(arg1, arg2);

function nextFunc() {
  var currentFuncName = nextFunc.caller.name;  
  var index = funcArray.indexOf(currentFuncName);
  if (index < funcArray.length)
    return funcArray[index+1];
}

通过数组funcArray可以轻松管理要执行的功能序列。每个函数的参数数量或类型不是固定的。此外,功能控制它们是否应该停止链接或继续执行下一个功能。

了解基本的Java技能非常简单。没有使用Promises的开销。

对于浏览器,“全局”被“窗口”替换。这是一个Node.js实现。但是,如果最小化JS代码,则数组中函数名称的使用将中断。当我要在服务器上使用它时,我不希望将其缩小。