2010-11-08 72 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

相关问题