2012-02-13 49 views
0

我有一個用於循環,超過一個關聯數組迭代。 foreach條目我必須做一個ajax請求,並用檢索的數據填充另一個數組。
問題是成功回調是異步的,所以它只有在循環迭代後才運行。這意味着我的數據數組充滿了最後一個Ajax請求結果的多個副本。 這是我的代碼(簡化):等待AJAX​​成功結束纔去槽下一迭代

var channels = { 
    "misured": "channel_misured", 
    "plan": "channel_plan" 
}; 
var data; //Initial data is empty 

function getData() { 
    data = new Array(); 

    for (var seriesData in channels) { 
     var currentData = new Array(); 
     $.ajax({ 
      type: "GET", 
      url: 'http://' + serverAddress + ':' + serverPort + '/GetChannelBufferAsJsonp?channelName=' + channels[seriesData] + '&callback=?', 
      dataType: "json", 
      async: false, 
      success: function (json) { 
       var time = new Date().getTime() + 3600000; 
       for (var i = 0; i < json.length; i++) { 
        currentData.push({ 
         x: time + i * 30000, 
         y: json[i] 
        }); 
       } 

       data.push({ 
        id: seriesData, 
        name: "Production " + seriesData, 
        data: currentData 
       }); 

      }, error: function() { 
       console.log("error", this); 
      } 
     }); 
    } 


} 

所以數據有2個元素(正確的),但他們都來自於「plan_channel」(這是我的數據源)。 我知道這是一個經典,衆所周知的「問題」(或功能)的Ajax請求,但我不明白我可以擺脫它。
你可以告訴如何等待成功回調才能結束,然後再進行下一次迭代?
非常感謝

+0

如果我明白你的問題,爲什麼不使用一個全局標誌/布爾你的Ajax請求啓動時控制? – FiveTools 2012-02-13 14:54:57

+0

做異步:假不工作? – 2012-02-13 14:55:47

+0

而不是將數據推入數組爲什麼不用數據清除數組? – Eli 2012-02-13 14:57:55

回答

1

這是我能看到重構代碼的唯一方法。儘管如此,它有點無意義。你已經設置了所有錯誤的海事組織,你不應該那樣做。我可以看到這樣做將是整個陣列中的一個Ajax請求發送到AJAX腳本,應對這一切在PHP(或其他)和吐回了格式的最佳方式,你希望它在JavaScript 。否則,你最好找到一個更好的方法來做到這一點。舉個例子,如果不是有一個for循環,你可能會有一個ajax請求,它會在成功調用中回調函數getData()

// add a global var... 
var inLoop; 
function getData() { 
    data = new Array(); 

    for (var seriesData in channels) { 
     inLoop = true; // set to true 
     var currentData = new Array(); 

     $.ajax({ 
      type: "GET", 
      url: 'http://' + serverAddress + ':' + serverPort + '/GetChannelBufferAsJsonp?channelName=' + channels[seriesData] + '&callback=?', 
      dataType: "json", 
      async: false, 
      success: function (json) { 
       // set inLoop to false to get out of loop below 
       inLoop = false; 
       var time = new Date().getTime() + 3600000; 
       for (var i = 0; i < json.length; i++) { 
        currentData.push({ 
         x: time + i * 30000, 
         y: json[i] 
        }); 
       } 

       data.push({ 
        id: seriesData, 
        name: "Production " + seriesData, 
        data: currentData 
       }); 

      }, error: function() { 
       console.log("error", this); 
      } 
     }); 

     // loop round this bit for a while 
     while(inLoop){ 
      // wait 
     } 
    } 


} 

這是我會怎樣改寫上面的代碼:

var channels = { 
    "first" : "hello world", 
    "second" : "goodbye world" 
} 

function getData(channel){ 
    $.ajax({ 
    url: 'http://whatever.com/channel='+channel, 
    success: function(){ 
     getData(nextchannel); 
    } 
    }); 
} 

爲了做到這一點,你可能要算你走的時候通過函數或東西,以便能夠通過下一個通道再次進入函數。

+0

但如果你有一段時間輪詢變量沒有瀏覽器說「有一個腳本沒有響應?」 – 2012-02-13 15:07:24

+0

嗯,我知道如何處理一般的Ajax請求,但在這個特殊的情況下我不能改變的方式我的「服務器」的答案,因爲我有在現場傳感器大範圍的硬件。反正你的解決方案似乎並沒有工作,因爲while循環永遠不會結束(中環內變量始終是真實 – andreapier 2012-02-13 15:10:55

+0

@EvilP嗯,多數民衆贊成完全可能的。它的愚蠢反正只是拖延while循環腳本。它更好地完全重寫該代碼。 @andreapier inLoop var在成功函數中設置爲false。但它不是編寫代碼的好方法。我建議從ajax請求的成功函數中重寫併發送一個新的請求到'getData',而不是使用for循環。 – 2012-02-13 15:14:29

1

對於同步AJAX調用您不能使用成功處理程序,一旦您的通話已完成必須返回結果。

嘗試使用Amplify.js(http://amplifyjs.com/)設置爲false的ASYC;它比jQuery ajax功能更容易使用,更加簡潔。不要被額外的圖書館推遲。

更新#1

您只需做到這一點

function getData() { 
    data = new Array(); 

    for (var seriesData in channels) { 
     var currentData = new Array(); 


    amplify.request.define("ajaxExample1", "ajax", { 
     url: 'http://' + serverAddress + ':' + serverPort + '/GetChannelBufferAsJsonp?channelName=' + channels[seriesData] + '&callback=?', 
     dataType: "json", 
     async: false, 
     type: "GET" 
    }); 

    // later in code 
    amplify.request("ajaxExample1", function(json) { 
     var time = new Date().getTime() + 3600000; 
     for (var i = 0; i < json.length; i++) { 
      currentData.push({ 
       x: time + i * 30000, 
       y: json[i] 
      }); 
     } 

     data.push({ 
      id: seriesData, 
      name: "Production " + seriesData, 
      data: currentData 
     }); 
    }); 

    } 
} 
+0

這個圖書館看起來不錯,我會試試。 – andreapier 2012-02-13 15:49:49