【问题标题】:How do I prevent functions, in an array of functions, from being executed before previous are finished如何防止函数数组中的函数在前一个函数完成之前执行
【发布时间】:2018-03-22 22:00:45
【问题描述】:

在尝试找到一种方法来运行一些存储在如下数组中的函数时,我生成了以下代码。

这很好用,但有时它似乎在前一个函数完成之前执行了一个函数。

如何防止在前面的代码完成之前执行下面代码中的函数?

具有多个函数“调用”和参数的数组示例

 ["A3",[6]],["B1",["TEST",4,13]],["A10",[2]],["A7",[1,5]]

从上述数组执行每个函数调用的 for 循环

function routineConverter(v){
    var routines = JSON.parse('[' + v + ']');
    for ( var  i=0; i < routines.length ; i++ ){
        switch (routines[i][0]) {
            case 'A1':
                routines[i] =  A1( routines[i][1] );                
                break;
            case 'A2':
                routines[i] =  A2( routines[i][1] );
                break;
            case 'A3':
                routines[i] =  A3( routines[i][1] );
                break;
            case 'A4':
                routines[i] =  A4( routines[i][1] );
                break;
            case 'A5':
                routines[i] =  A5( routines[i][1] ); 
                break;
            case 'A6':
                routines[i] =  A6( routines[i][1] );
                break;
            case 'A7':
                routines[i] =  A7( routines[i][1] ); 
                break;
            case 'A8':
                routines[i] =  A8( routines[i][1] );
                break;
            case 'A9':
                routines[i] =  A9( routines[i][1] ); 
                break;  
            case 'A10':
                routines[i] =  A10( routines[i][1] ); 
                break;  
            case 'B1': 
                routines[i] =  B1( routines[i][1] ); 
                break;
            case 'B2': 
                routines[i] =  B2( routines[i][1] );
                break;  
            case 'E':
                routines[i] =  conditionalAction( routines[i][1] ); 
                break;
            case 'X1':
                //console.log(routines[i][1]);
                routines[i] =  REMOVE(routines[i][1] ); //B1( routines[i][1] ); 
                break;  
          }
    } 
    var a = [routines];
}

函数示例:

function A1(p) {
    $('#tbl tr td:nth-child(' + parseInt(p) + ')').after('<td></td>');  
}

【问题讨论】:

  • 只有当你在某处执行一些异步代码时才会发生这种情况,你是否在任何函数中运行了一些?你能提供一个可运行的sn-p吗?
  • 你尝试过承诺吗​​pan>
  • 这是异步的吗?如果不是,你可以以 0 的间隔使用 setTimeout。如果是异步的,则使用 Promise。
  • 如果这不是异步的,则保证您的函数在下一个开始执行之前完成。这是由于 Javascript 的同步、单线程(除非您使用网络工作者)性质。
  • 这是一个非常奇怪的请求。用例是什么?我相当肯定一定有更好的解决方案。

标签: javascript jquery


【解决方案1】:

我留下了一条评论,询问您的问题是什么,因为我期望有更好的解决方案。无论如何,我有一个答案给你。您需要将要调用的函数放入对象中才能使该解决方案起作用。您还需要 ES6 支持或 babelify 代码。

const calls = [["A3",[6]],["B1",["TEST",4,13]],["A10",[2]],["A7",[1,5]]];

const functions = {
  A3: function (...args) { 
    console.log('A3', args);
  },
  B1: function (...args) {
    console.log('B1', args);
  },
  A10: function (...args) {
    console.log('A10', args);
  },
  A7: function (...args) {
    console.log('A7', args);
  }
};

const functionCaller = fns =>
  fns.map(([fn, ...args]) => functions[fn](...args));
  
console.log(functionCaller(calls));

这里的functionCaller 函数接收调用数组,例如在顶部定义的那些,并映射到它们,返回它们的结果数组。

地图通过解构数组来工作,初始元素始终是函数的名称,其余的是参数,使用destructuring syntaxspread operator 将它们分隔到自己的数组中

然后我们将此函数名作为对象的键,调用带有参数的特定方法。

当您运行 sn-p 时,您将看到正确的函数名称以及传递的参数,但将返回一个未填充的数组,因为定义的函数都没有返回任何内容。如果他们这样做了,我们会看到这个数组被填充。

【讨论】:

  • 这看起来很有希望。问题是顺序是不可预测的。顺序一直在变化(A3、B1、A10等也可以是B1、A10、A3等)
  • 这将始终按照提供的顺序执行函数。
【解决方案2】:

我承认这不是最好的方法,但是您可以在执行函数的 and 处返回例如 if ,您可以使用这个 int 来启动另一个函数。

但这是一个折中的解决方案。

【讨论】:

    【解决方案3】:

    我假设您使用的是异步代码。您的示例中的同步代码已经可以按照您希望的方式运行,函数是按顺序调用的。

    为了使这项工作异步进行,您可以利用async/await 和承诺。这样做会调用async 函数,但您的 switch 语句将等到它们完成后才允许线程继续循环。这可以在我附加的示例中看到。

    请注意,如果在不使用 await 的情况下异步调用,C 的超时时间最低,并且会首先完成。然而,由于使用 async 函数和 await C 是最后一个被调用的函数。

    var routines =  [["A1",["PARAM-A"]],["B1",["PARAM-B"]],["C1",["PARAM-C"]]];
    
    function A1(param) {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve(`A1 FUNC: ${param}`);
        }, 1000);
      });
    }
    
    function B1(param) {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve(`B1 FUNC: ${param}`);
        }, 500);
      });
    }
    
    function C1(param) {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve(`C1 FUNC: ${param}`);
        }, 100);
      });
    }
    
    async function routineConverter(routines){
        var results = []
        for ( var  i=0; i < routines.length ; i++ ) {
        
            // waits for the promise to resolve
            let returnedValue = await funcSwitch(routines, i)
            console.log(returnedValue)
            
            //assign value
            results[i] = returnedValue;
        } 
        
        //print out final results
        console.log(results)
    }
    
     function funcSwitch(routines, i) {
    	var returnValue;
        
        switch (routines[i][0]) {
          case 'A1':
            returnValue =  A1( routines[i][1] );                
            break;
          case 'B1':
            returnValue =  B1( routines[i][1] );
            break;
          case 'C1':
            returnValue =  C1( routines[i][1] );
            break;
        }
        
        return returnValue;
    }
    
    routineConverter(routines)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多