好吧,我有一个ajax调用,可以重现json对象。
我想要做的事情的想法是获取标记的所有记录的列表,并对地理编码进行反向查找并保存回数据库,但是作为批处理
我想遍历数据,然后执行额外的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调用在处理下一条记录之前就有时间执行。
END EDIT ------------------------------ 任何想法或指示将不胜感激
感谢
答案 0 :(得分:1)
我不认为“一切运行得太快”是对您遇到的任何问题的准确诊断。
我看到的一件事是你从其他ajax调用的成功fn启动了ajax调用。我不知道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命名使用camelCase和verbNoun命名。所以,processBatch()
和lookupAddress()
,而不是processbatch()
和address_lookup()
。
修改强>
以下是如何思考它:当您调用ajax调用时,您告诉浏览器发送HTTP请求。通常在您调用调用时,您会传递一个“成功”函数,当收到HTTP响应时,该函数会被调用。正如您所知,使用浏览器时,响应可以快速到达,也可以不那么快。当您在循环中调用ajax调用时,您告诉浏览器发送N个并发HTTP请求。不一定是你想要的。
我在这里建议的是一次调用一个AJAX调用(例如,到地址编码器)并且仅从成功fn调用下一个调用 - 也就是说,从第一个调用收到响应之后一。此外,如果您使用setTimeout()
执行此操作,则将避免深度嵌套。