JSON请求在jQuery中无法正常工作每个函数
问题描述:
如果对于包含类.event
的每个div更改了值,我正在使用以下代码检索给定位置的经度和纬度。JSON请求在jQuery中无法正常工作每个函数
时遇到的问题是,只有两个结果从该代码发生:
- 的值从一个JSON请求返回被用于每
lat
和lon
可变 - 变量
lat
和lon
保持完全一样,就好像它们保持不变,所以JSON值不会被替换。
下面是我使用的代码:
$(".button").click(function(){
data = "";
$(".event").each(function(){
original = $(this).find(".address").data("original");
location = $(this).find(".address").html();
lat = $(this).find(".lat").html();
lon = $(this).find(".lon").html();
if (original !== location) {
$.getJSON("http://nominatim.openstreetmap.org/search?q="+location+"&format=json&polygon=1&addressdetails=1", function(result) {
lat = result[0].lat;
lon = result[0].lon;
});
}
data = data + randomNumber() + ": " + lat + " " + lon + ",";
});
$(".data").val(data);
$(".form").submit();
});
可变data
将包含含有类event
每个格的lat
和lon
。除非用户更改地址,否则这些值将保持不变,在此时他们将通过JSON请求再次被检索。
然后提交表格。
我该如何解决这个问题?谢谢
答
$.getJSON
是异步的,你不能引用回调函数以外的结果。并且您不想提交表单直到全部 AJAX请求完成。
$.getJSON()
返回Deferred
。你可以制作所有这些数组,并使用$.when()
来等待它们。
$(".button").click(function() {
var promises = [];
var data = "";
$(".event").each(function() {
var original = $(this).find(".address").data("original");
var location = $(this).find(".address").html();
var lat = $(this).find(".lat").html();
var lon = $(this).find(".lon").html();
if (original !== location) {
promises.push($.getJSON("http://nominatim.openstreetmap.org/search?q=" + location + "&format=json&polygon=1&addressdetails=1", function(result) {
var lat = result[0].lat;
var lon = result[0].lon;
data += randomNumber() + ": " + lat + " " + lon + ",";
}));
} else {
data += randomNumber() + ": " + lat + " " + lon + ",";
}
});
$.when.apply($, promises).done(function() {
$(".data").val(data);
$(".form").submit();
});
});
注意,值的data
顺序是不可预知的,因为AJAX请求不一定在他们发送的顺序返回。
你还应该习惯于将变量声明为var
(或在ES6中为let
)。
答
我想你应该打电话$.getJSON
然后处理所有的结果,而得到他们所有。
如果$.getJSON
对于位置不是必需的,则可以立即创建延迟/承诺来模拟异步调用。这样我们就可以处理相同类型的结果(jQuery Promise Object)。
这里是代码(未测试),并评论:
$(".button").click(function() {
// data = "";
// unnecessary
// $(".event").each(function() {
// use map to get promise objects for every ".event"
var promises = $(".event").map(function() {
original = $(this).find(".address").data("original");
location = $(this).find(".address").html();
// lat = $(this).find(".lat").html();
// lon = $(this).find(".lon").html();
// not need here
if (original !== location) {
return $.getJSON("http://nominatim.openstreetmap.org/search?q=" + location + "&format=json&polygon=1&addressdetails=1", function(result) {
lat = result[0].lat;
lon = result[0].lon;
});
} else {
// make value type same as json, it's a array of { lat, lon }
return $.Deferred().resolve([{
lat: $(this).find(".lat").html(),
lon: $(this).find(".lon").html()
}]).promise();
}
// data = data + randomNumber() + ": " + lat + " " + lon + ",";
// do it later, after all promise resolved.
});
$.when.apply(null, promises)
.done(function() {
// convert arguments to a array
var args = [].slice.apply(arguments);
data = args
.map(function(models) {
// convert each model to a string
var model = models[0];
return randomNumber() + ": " + model.lat + " " + lon;
})
// join each part with separator ','
.join(",");
// while got data, deal with it
$(".data").val(data);
$(".form").submit();
});
});
'$ .getJSON'是异步的。你在回调函数执行前设置'data'。 – Barmar