2010-11-08 70 views
0

好的,我有一個ajax調用recives一個json對象。jquery暫停循環,直到全局條件得到滿足

的whatn我試圖做的想法是得到舉報的所有記錄的列表,以及地理編碼他們做一個反向查找並保存到數據庫中,但作爲一個批次

我在想循環數據,然後執行額外的ajax調用(將對數據進行地理編碼),然後執行另一個ajax調用以保存到數據庫。

問題出在我的for循環中,一切運行得太快,調用和瀏覽器崩潰之間沒有停頓,或者保存到數據庫函數會添加錯誤的數據。

$('#geo_batch').click(function(){ 
      var ajax_load = "<label><img src='/images/icons/loadinfo.gif' alt='saving location...' /> Loading data...</label>"; 
      $("#batch_detail").html(ajax_load); 
      $('#batch_buttons').hide(); 
      saveall = true; 
      var form = $("form"); //Grab the form element from the DOM 
      //alert(form.serialize()); 
      var mydata = form.serialize(); 
      $.ajax({ 
       type: "POST", 
       url: 'geo_getupdate_list.php', 
       data: mydata, 
       dataType: 'json', 
       success: function(dat) { 
        processbatch(dat);// process the returned data 
       }, 
       error: function(dat) { //Triggered if an error communicating with server 
        //alert('fail'); 
        $("#batch_detail").html('<label>There was an error: '+dat+'<label>'); 
        $('#batch_buttons').show(); 
       } 
      }); 
      return false; //Ignore the default behavior of the button click 
     }); 

過程數據功能

function processbatch(dat){ 
      // Cache the batch_detail element 
      $("#batch_detail").html('<label>Locations have been retrieved:<br>' + dat + '<label>'); 
      $('#batch_buttons').show(); 
      var count = dat.location.length - 1; 
      for(i=0; i < count; i++){ 
       $('#batch_detail').append('<li>address: ' + dat.location[i].geoaddr_mdt + 'flag: ' + dat.location[i].flag_mdt+'</li>'); 
       $('#id_mdt').val(dat.location[i].id_mdt); 
       $('#entrytype').val(dat.location[i].idedt_mdt); 
       $('#name').val(dat.location[i].name_mdt); 
       $('#geo_addr').val(dat.location[i].geoaddr_mdt); 
       $('#telephone').val(dat.location[i].telephone_mdt); 
       $('#email').val(dat.location[i].email_mdt); 
       $('#geo_detail').val(dat.location[i].displayaddr_mdt); 
       $('#website').val(dat.location[i].website_mdt); 
       //$('#active').val(dat.location[i].active_mdt); 
       var address = dat.location[i].geoaddr_mdt; 
       // if address is not empty 
       if(address != '') { 
        address_lookup(address, region, 'update'); 
       }; 
      }; 
     }; 

地址查找功能

function address_lookup(address, region, savetype) { 
     // set default region 
     if(region==null || region == '') { 
      region = 'uk'; 
     }; 
     // address not empty 
     if(address != '') { 
      //clear existing markers<br /> 
      if(savetype == 'save'){ 
       removemarkers(); 
      }; 
      $('#geo_detail').html('<label>Geocoding address...</label>'); 
      // lookup the address 
      geocoder.geocode({'address':address,'region':region}, function(results, status) { 
       // if the address was found 
       if(status == google.maps.GeocoderStatus.OK) { 
        $str = '<label>Geocode Successful<br> Lattitude: '+results[0].geometry.location.lat()+' Longitude: '+results[0].geometry.location.lng()+'<br> The address is displayed below and will be stored in the database.<br> If the address is incorrect you may edit it before saving the location to the database.<br>If the marker is in the wrong location you may drag it to where you believe it should be.</label>'; 
        $('#geo_detail').html($str); 
        // insert lat/long into form 
        $('#lat').val(results[0].geometry.location.lat()); 
        $('#lng').val(results[0].geometry.location.lng()); 
        // create new lat/long object 
        latlng = new google.maps.LatLng(results[0].geometry.location.lat(),results[0].geometry.location.lng()); 
        $('#disp_addr').val(address); 
        $('#form_buttons').show(); 
        $('#detail_address').show(); 
        //reverselookup(results[0].geometry.location.lat(), results[0].geometry.location.lng()); 
        // set zoom option 
        map.setZoom(15); 
        // center the map on the new location 
        map.setCenter(results[0].geometry.location); 
        createMarker(map, latlng, true, false); 
        if(savetype ='update'){ 
         savedata('update'); 
        }; 
        if(savedata='save'){ 
         savedata('save'); 
        }; 
       } else { 
        // display error 
        $('#geo_detail').append('<label>Geocoder failed to retrieve address: '+status+'</label>'); 
        $('#disp_addr').val($('#geo_addr').val()); 
       }; 
      }); 
     }; 
    }; 

編輯在回答Zacks的第一個評論----

我要顯示的每個結果作爲它正在被處理,然後將結果輸出到geo_detail div,所以有一個處理過的記錄和關聯的列表這意味着我希望讓用戶在處理每條記錄時檢查每條記錄,因此循環會暫停,直到用戶關閉保存按鈕,這可能會將全局變量設置爲true,這樣我的循環會檢查並等待,然後開始我需要某種暫停,以便在處理下一條記錄之前各種ajax調用有時間執行。

編輯完------------------------------ 任何意見或指針將不勝感激

感謝

+0

你的目標是什麼?要一次顯示所有結果(例如每5秒一次),或顯示結果列表? – 2010-11-08 12:11:09

+0

嗨zack,看到我的編輯在原來的問題... – 2010-11-08 12:29:11

回答

1

我不認爲「一切運行得太快」是對您遇到的任何問題的準確診斷。

我看到的一件事是,你有ajax調用從其他ajax調用的成功fn啓動。我不知道ajax lib是否可以重入。你可能想避免這種情況。

我會這樣做的方式是引入異步混合。使用setTimeout()來調用您的processbatch()函數。然後它將異步運行,就第一個ajax調用而言。

還可以考慮使用異步來調用goecoder。只有在所有其他地理編碼器請求完成後才發送新的地理編碼器請求。你這樣做的方式,你一次發送它們。 (也許這就是你所說的「一切運行得太快」)。

執行此操作的方法:接受地址對象和索引數組到address_lookup。在第i個地址上調用地理編碼器。然後,當調用完成(成功或失敗)時,增加索引,並使用setTimeout再次調用address_lookup。

這樣,您最多隻能獲得一次傑出的地理編碼調用。

它看起來像這樣的代碼:

var delay = 140; 
function doAllAddresses(a, ix, callback) { 

    // handle any addresses. 
    // Test the list index for validity. If valid, 
    // Do the geocode, then increment the list index, 
    // and call "myself" to handle additional 
    // addresses. When no more addresses remain, invoke 
    // the 'done' callback. 

    if (ix < a.length) { 
     invokeGeocoderForOneAddress(a[ix], function() { 
      // success function - gets invoked only when call to geocoder returns 
      ix++; 
      setTimeout(function(){doAllAddresses(ltr, ix, callback);}, delay); 
     }); 
     return; 
    } 

    callback(); 
} 

// kickoff: 
doAllAddresses(addresses, 0, function() { alert("all addresses are done.");}); 

編輯
PS:我建議你修正內容的FN命名使用駝峯和verbNoun命名。所以,processBatch()lookupAddress(),而不是processbatch()address_lookup()


編輯
下面是如何看待它:當你調用一個Ajax調用,你告訴瀏覽器發送一個HTTP請求。通常,在您調用該調用時,您會在收到HTTP響應時傳遞一個「成功」函數,該函數會爲您調用。正如你使用瀏覽器所知道的那樣,響應可以很快到達,或者不是那麼快。當您在循環中調用ajax調用時,您告訴瀏覽器發送N個併發HTTP請求。不一定是你想要的。

我在這裏提出的建議是每次調用一次AJAX調用(例如對地理編碼器),並且只從成功fn調用下一個調用 - 也就是說,在從第一。另外,如果你使用setTimeout()來做,你將避免深度嵌套。

+0

感謝您的回覆cheeso 最初的調用是ajax調用,它返回json數據,我需要從該成功函數運行此功能?我假設a是json對象的計數,ix是某種基本索引,如0開始計數?對不起,但我真的不明白的代碼。並且我不確定我需要設置回調函數 – 2010-11-08 13:08:06

+0

否 - 從原始ajax調用的成功fn異步調用此fn(它與您的'processbatch()')相同(使用setTimeout)。 a是數組,ix是數組中的索引。有關啓動示例,請參閱上面的代碼,在「啓動」的評論下。回調函數是地址解析器處理所有地址時調用的函數。只是一個方面的評論 - 這對了解Javascript中的異步編程非常有價值。花時間理解這一點,你會很高興你做到了。爲了能夠成功地完成AJAX,這是至關重要的。 – Cheeso 2010-11-08 13:23:10

+0

好的謝謝你的澄清我會試一試,看看我怎麼下去! – 2010-11-08 15:03:42

相關問題