2016-02-11 138 views
1

我正在创建一个React应用程序,该应用程序涉及到几个调用一些webapi REST服务来完成我的事情。部分应用程序是某些请求的审批流程。存在能够创建与由一个UI这些流的特定角色:Javascript中的异步操作。

  1. ,该目录由基数排序的过程的步骤的表(这意味着顺序)。这些步骤还包括演员和地位。
  2. 上的每一行的按钮安排高达每行上/下
  3. 按钮删除的相应行
  4. A按钮以添加新的步骤。

我所做的是允许用户使用Javascript(主要是数组操作)进行更改,同时使用操作和相应的数据填充动作缓冲区数组。例如。

this.actionsBuffer.push({ 
     action: "ADD_STEP", 
     data: next 
    }); 

当用户对排列感到满意时,她可以按下“接受”按钮。它所做的是迭代actionsBuffer数组并执行由动作字段确定的适当的REST服务。

我知道我的描述可能看起来太详细了,但我希望你知道上下文。

问题: 我现在的问题是,由于调用是异步的,我怎样才能保证动作将按这个顺序执行。

一些代码片段:

这种迭代,并调用determineAction

onAccept: function (e) { 
     e.preventDefault(); 
     var self = this; 
     //console.log("Gonna save:",JSON.stringify(this.state.workflow)); 

     var ret=null; 
     // First we do actions in actionsBuffer 
     for(var i=0;i<this.actionsBuffer.length;i++) 
     { 
      ret = self.determineAction(this.actionsBuffer[i]); 
      if (ret==false) 
       break; 
      else 
       this.actionsBuffer.splice(i,1); 
      ret=null; 
     } 


     this.saveAll(); 
    }, 

而且determineAction。请原谅调试控制台消息

determineAction: function (action) { 

     var url=""; 
     var verb=""; 

     switch(action.action) 
     { 
      case "ADD_STEP": 
       delete action.data.ActorList; 
       url=this.props.server+"/workflows/"+this.props.workflowid+"/steps"; 
       verb="POST"; 
       break; 
      case "DELETE_STEP": 
       url=this.props.server+"/workflows/"+this.props.workflowid+"/delete/"; 
       verb="POST"; 
       break; 
     } 

     console.log("Going to call url:",url," with varb:",verb," and data:",action.data); 
     $.ajax({ 
      type: verb, 
      url: url, 
      data: JSON.stringify(action.data), 
      processData:false, 
      contentType: 'application/json' 
     }) 
      .success(function(data) { 
       return true; 
       //self.props.onclose(self.state.workflows.WorkflowId); 
      }) 
      .error(function(jqXhr) { 
       console.log(jqXhr); 
       return false; 
      }); 
    }, 
+0

所有相关信息都是好信息man! – phenxd

+0

看看[如何在Javascript中按顺序运行promise?](http://stackoverflow.com/q/18386753/1048572) – Bergi

回答

0

你是不是在等待determineAction完成。让它返回一个承诺,并等待它在你调用它的地方。你的循环也必须是异步的。我创建了一个可能不完全符合您需要的尝试,但向您显示了您应该移动的方向。

onAccept: function (e) { 
    e.preventDefault(); 
    var self = this; 


    var ret=null; 
    // First we do actions in actionsBuffer 
    var i = 0; 
    function makeRequest() { 
     self.determineAction(self.actionsBuffer[i]).success(function() { 
      i++; 
      if (i >= (self.actionsBuffer.length) { 
       self.saveAll(); 
      } else { 
       makeRequest(); 
      } 

     }).error(function(){ 
      self.saveAll(); 
     }) 
    } 
    makeRequest() 

    this.saveAll(); 
}, 


determineAction: function (action) { 

    var url=""; 
    var verb=""; 

    switch(action.action) 
    { 
     case "ADD_STEP": 
      delete action.data.ActorList; 
      url=this.props.server+"/workflows/"+this.props.workflowid+"/steps"; 
      verb="POST"; 
      break; 
     case "DELETE_STEP": 
      url=this.props.server+"/workflows/"+this.props.workflowid+"/delete/"; 
      verb="POST"; 
      break; 
    } 

    console.log("Going to call url:",url," with varb:",verb," and data:",action.data); 
    return $.ajax({ 
     type: verb, 
     url: url, 
     data: JSON.stringify(action.data), 
     processData:false, 
     contentType: 'application/json' 
    }); 
}, 
0

而不是迭代您的动作阵列与for循环同步。相反,将它视为一个队列。

  1. 从队列中取出第一项并执行它。
  2. 当异步工作完成后,从 队列取另一个项目。
  3. 重复,直到清除队列。

下面是一个简单的例子。

function processActions(actionQueue) { 
    if(actionQueue.length == 0) return; 

    // take the first action from the queue 
    var action = actionQueue[0]; 

    // assuming determineAction() returns a promise 
    determineAction(action) 
    .then(function() { 
     var remainingActions = actionQueue.slice(1); 

     // we know this action has completed, so we can pass 
     // the remaining actions to be processed 
     processActions(remainingActions); 
    }); 
}