2016-02-11 135 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); 
    }); 
}