Javascript setTimeout在同步ajax中无法按预期工作
我有一个函数,它在长度为n的数组中循环并构建Javascript setTimeout在同步ajax中无法按预期工作,javascript,jquery,ajax,google-maps,Javascript,Jquery,Ajax,Google Maps,我有一个函数,它在长度为n的数组中循环并构建工厂时多次被调用,每个工厂都使用同步ajax调用,它查询Google Maps API,因此我需要限制它。我在函数上设置了一个setTimeout(),该函数在5秒钟内调用地理编码,以确保安全,并将该setTimeout嵌套在ajax的done()函数中。问题是超时设置了延迟,然后继续进行下一个ajax调用。然后,第一个地理代码在第一个ajax完成5秒后出现 function Plant(plantName, address, inventory){
工厂时多次被调用,每个工厂都使用同步ajax调用,它查询Google Maps API,因此我需要限制它。我在函数上设置了一个setTimeout()
,该函数在5秒钟内调用地理编码,以确保安全,并将该setTimeout嵌套在ajax的done()函数中。问题是超时设置了延迟,然后继续进行下一个ajax调用。然后,第一个地理代码在第一个ajax完成5秒后出现
function Plant(plantName, address, inventory){
this.plantName = plantName;
this.address = address;
this.inventory = inventory;
this.latCoord = 0;
this.lngCoord = 0;
this.pullCoordinatesFromDB();
}
Plant.prototype.pullCoordinatesFromDB = function(){
var $this = this;
console.log("pulling farm coords for: "+$this.address);
$.ajax({
async: false,
type: "POST",
data: {
address: $this.address
},
url: "actions/getCoordinates.php"
}).always(function(){
console.log("request sent");
}).fail(function(jqXHR, textStatus, errorThrown){
console.log("failed");
console.log(textStatus);
console.log(errorThrown);
}).done(function(data){
console.log("got farm coords");
if(data.numRows){
$this.latCoord = data.latCoord;
$this.lngCoord = data.lngCoord;
}
else{
setTimeout( $this.pullCoordinatesFromAPI , 5000);
}
});
return 1;
};
Plant.prototype.pullCoordinatesFromAPI = function(){
var $this = this;
GEOCODER.geocode( {'address': $this.address}, function(results, status){
if (status == google.maps.GeocoderStatus.OK) {
var location = results[0].geometry.location;
$this.latCoord = location.lat;
$this.lngCoord = location.lng;
console.log("pushing");
$this.pushCoordinatesToDB();
}
else{
console.log("Could not successfully query the API: "+status);
}
});
return 1;
};
输出似乎将输出记录为:
- 拉农场坐标:
- 发送请求
- 有农场合作社吗
- 拉农场坐标:
- 发送请求
- 有农场合作社吗
- 拉农场坐标:
- 发送请求
- 有农场合作社吗
- 策划
- 无法成功查询API:超过\u查询\u限制
您可以通过以下方法解决此问题:
var queue = $({});
var deferreds = [];
Plant.prototype.pullCoordinatesFromDB = function(dfd){
var $this = this;
console.log("pulling farm coords for: "+$this.address);
$.ajax({
type: "POST",
data: {
address: $this.address
},
url: "actions/getCoordinates.php"
}).always(function(){
console.log("request sent");
}).fail(function(jqXHR, textStatus, errorThrown){
console.log("failed");
console.log(textStatus);
console.log(errorThrown);
}).done(function(data){
console.log("got farm coords");
if(data.numRows){
$this.latCoord = data.latCoord;
$this.lngCoord = data.lngCoord;
}
else{
queue.delay(5000).queue(function(next){
$this.pullCoordinatesFromAPI();
dfd.resolve();
next();
});
}
});
return 1;
};
var plants = [Plant, Plant, ...];
for(var i = 0; i < plants.length; ++i){
var dfd = new $.Deferred();
plants[i].pullCoordinatesFromDB();
deferreds.push(dfd);
}
$.when.apply(null, deferreds).done(YOUR_CALLBACK_FUNCTION);
var queue=$({});
风险值递延=[];
Plant.prototype.pullCoordinates fromdb=函数(dfd){
var$this=这个;
log(“为“+$this.address”拉农场坐标);
$.ajax({
类型:“POST”,
数据:{
地址:$this.address
},
url:“actions/getCoordinates.php”
}).always(函数(){
控制台日志(“已发送请求”);
}).fail(函数(jqXHR、textStatus、errorshown){
console.log(“失败”);
console.log(textStatus);
console.log(错误抛出);
}).完成(功能(数据){
log(“得到农场坐标”);
if(data.numRows){
$this.latCoord=data.latCoord;
$this.lngCoord=data.lngCoord;
}
否则{
queue.delay(5000).queue(函数)(下一步){
$this.pullCoordinatesFromAPI();
解析();
next();
});
}
});
返回1;
};
植物变量=[植物,植物,…];
对于(变量i=0;i
编辑:添加延迟以查看api的所有调用何时完成。异步:false,
是否真的有必要?请注意,对于同步请求,不推荐使用承诺回调(完成、失败、始终等)。如果希望所有调用都同步运行,只需在不超时的情况下调用函数?在数据库调用后暂停5秒不会改变您的查询。问题是您连续调用Plant
的次数太多了。@epascarello我很困惑。也许我没有完全掌握sync vs async,但我想要的是检查数据库,如果那里没有条目,请转到api,然后一旦访问(从DB或api),启动Plant的下一个构造函数。我认为ajax在默认情况下是异步的,因此可以在后台运行而不冻结JS。我希望它冻结JS,以便在当前调用完成之前不会启动下一个调用。谢谢!我以前从未见过jQuery队列!每次我创建工厂时,它都会从数据库或API中获取值。在我多次调用Plant的代码中,我将这些Plant添加到一个数组FULL_列表中。然后我想通过对各种植物的特性进行数学计算来处理完整的清单。在我的主脚本中,是否可以等到所有这些植物都被完全创建(比如等到队列结束)才能继续?@timolescher您可以使用jQuery.Deferred
,查看我的更新答案。