我有一个像这样的ajax代码:
$.ajax({
type: "post",
async: false,
url: "/FindAVet/Search",
data: '{"vetname":"' + $("#VetName").val() + '","lat":"' + objlatitude + '","lng":"' + objlongitude + '","radius":"' + $("#hdnRadius").val() + '","searchAll":"' + searchAll + '"}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
if (result.IsValid == true) {
$("#divMapContainer").show();
$("#placeholderServiceagent").html('');
$("#placeholderServiceagent").show();
$("#placeholderServiceagent").html(result.Datavalue);
$("#noserviceagentstatus").hide();
var arrLoc = result.Locations.split(";");
var arrInf = result.InfoWindowContents.split(";");
var source, destination, distance;
source = $("#SuburbOrPostcode").val();
var service = new google.maps.DistanceMatrixService();
var arr2dLoc = [];
var arr2dInf = [];
for (var i = 0; i < arrLoc.length; i++) {
arr2dLoc[i] = arrLoc[i].split(",");
}
var j = 1;
for (var i = 0; i < arrInf.length; i++) {
arr2dInf[i] = arrInf[i].split(",");
var strarr2dInf = arr2dInf[i].toString();
var dom_des = $($.parseHTML(strarr2dInf));
destination = dom_des.find('.des').text();
service.getDistanceMatrix({
origins: [source],
destinations: [destination],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, function (response, status) {
if (status == google.maps.DistanceMatrixStatus.OK && response.rows[0].elements[0].status != "ZERO_RESULTS") {
distance = response.rows[0].elements[0].distance.text;
var spDistance = $("#distance" + j);
spDistance.prepend(distance);
var li = $("#" + j);
var distancewithoutkmtext = distance.replace(' km', '');
li.attr("id", distancewithoutkmtext);
j++;
} else {
alert("Unable to find the distance via road.");
}
});
}
init_map('map_canvas', 18, arr2dLoc, arr2dInf);
}
else {
$("#divMapContainer").hide();
$("#placeholderServiceagent").hide();
$("#noserviceagentstatus").show();
}
$("#lblServiceAgentStatus").html(result.Message);
},
complete: function (data) {
var elems = $('.storeList').children('li');
elems.each(function (idx, li) {
alert($(this).attr("id"));
});
}
我已经改变了li标签的id:
var li = $("#" + j);
var distancewithoutkmtext = distance.replace(' km', '');
li.attr("id", distancewithoutkmtext);
但是在完整功能中,当我尝试通过调用alert函数来显示<li>
标签的id时,会显示id的旧值,如下所示:
这是错误的(1,2,3,4 ......是li标签的id的原始值)
答案 0 :(得分:0)
您正在更改service.getDistanceMatrix()
的异步回调函数中的ID。但是您要在原始$.ajax
的回调函数中提醒ID,因此第二个回调函数尚未运行。
将带有alert
的循环移动到第二个回调函数,您将看到正确的结果。
$.ajax({
type: "post",
async: false,
url: "/FindAVet/Search",
data: '{"vetname":"' + $("#VetName").val() + '","lat":"' + objlatitude + '","lng":"' + objlongitude + '","radius":"' + $("#hdnRadius").val() + '","searchAll":"' + searchAll + '"}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(result) {
if (result.IsValid == true) {
$("#divMapContainer").show();
$("#placeholderServiceagent").html('');
$("#placeholderServiceagent").show();
$("#placeholderServiceagent").html(result.Datavalue);
$("#noserviceagentstatus").hide();
var arrLoc = result.Locations.split(";");
var arrInf = result.InfoWindowContents.split(";");
var source, destination, distance;
source = $("#SuburbOrPostcode").val();
var service = new google.maps.DistanceMatrixService();
var arr2dLoc = [];
var arr2dInf = [];
for (var i = 0; i < arrLoc.length; i++) {
arr2dLoc[i] = arrLoc[i].split(",");
}
var j = 1;
for (var i = 0; i < arrInf.length; i++) {
arr2dInf[i] = arrInf[i].split(",");
var strarr2dInf = arr2dInf[i].toString();
var dom_des = $($.parseHTML(strarr2dInf));
destination = dom_des.find('.des').text();
service.getDistanceMatrix({
origins: [source],
destinations: [destination],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, function(response, status) {
if (status == google.maps.DistanceMatrixStatus.OK && response.rows[0].elements[0].status != "ZERO_RESULTS") {
distance = response.rows[0].elements[0].distance.text;
var spDistance = $("#distance" + j);
spDistance.prepend(distance);
var li = $("#" + j);
var distancewithoutkmtext = distance.replace(' km', '');
li.attr("id", distancewithoutkmtext);
j++;
} else {
alert("Unable to find the distance via road.");
}
var elems = $('.storeList').children('li');
elems.each(function(idx, li) {
alert($(this).attr("id"));
});
});
}
init_map('map_canvas', 18, arr2dLoc, arr2dInf);
} else {
$("#divMapContainer").hide();
$("#placeholderServiceagent").hide();
$("#noserviceagentstatus").show();
}
$("#lblServiceAgentStatus").html(result.Message);
}
});
&#13;
答案 1 :(得分:0)
我的代码中已经标记了很多,所以我会尝试在一个例子中解释一下
假设我们可以重写您的代码,使其看起来像这样:
$.ajax({
type: "post",
url: "/FindAVet/Search",
// etc
success: function successHandler(result) {
// ...
},
complete: function completeHandler() {
// ...
}
})
现在,让我们来看看successHadler
function successHandler(result) {
// Do stuff with html
// parse result
// for each location;info pair:
// call service.getDistanceMatrix
// parse distanceMatrix
// modify DOM accordingly
}
在completeHandler中,大概是,你想要使用修改过的DOM进一步工作,但你不能。
这是因为对service.getDistanceMatrix
的调用是异步的。实际上,$.ajax
发生等待的事情,每次异步调用都会发生这种情况。由于service.getDistanceMatrix
是异步的,
在它调用谷歌之后,它就等了。所以,ajax做1,2,3。在3. service.getDistanceMatrix被调用。
service.getDistanceMatrix
具有与$ .ajax类似的机制。所以,它再次等待。
现在,如果某些内容等待,则事件循环会在队列中查找它可以在此期间处理的事件。
而且,它现在看到前一个$.ajax
有第4步,所以很高兴能够使用它。
几毫秒后,service.getDistanceMatrix也会获取数据并触发你的回调,其中包含:
// parse distanceMatrix
// modify DOM accordingly
但那已经太晚了,因为completeHandler已经完成了
那么,如何摆脱这种局面呢?
最简单的解决方案是将来自completeHandler的代码放在successHandler中。但这不是全部。
$.ajax({
type: "post",
url: "/FindAVet/Search",
// etc
success: function successHandler(result) {
// Do stuff with html
// parse result
// for each location;info pair:
// call service.getDistanceMatrix
// parse distanceMatrix
// modify DOM accordingly
completeHandler();
}
})
完整处理程序现在仍然不等待getDistanceMatrix的异步调用完成。
我们可以将service.getDistanceMatrix
包装成promise以使其异步:
const service = new google.maps.DistanceMatrixService()
function getDistanceMatrixAsync(parameters) {
return new Promise(function(resolve, reject) {
service.getDistanceMatrix(parameters, function(response, status) {
if (status == google.maps.DistanceMatrixStatus.OK && response.rows[0].elements[0].status != "ZERO_RESULTS") {
resolve(response)
}
else {
reject('Unable to find the distance via road.')
}
})
})
}
// usage:
// outside the loop - this is needed because of the asynchronous code inside the for loop.
let k = 1
// inside the loop
getDistanceMatrixAsync({
origins: [source],
destinations: [destination],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
})
.then(function (response) {
let j = k;
distance = response.rows[0].elements[0].distance.text;
var spDistance = $("#distance" + j);
spDistance.prepend(distance);
var li = $("#" + j);
var distancewithoutkmtext = distance.replace(' km', '');
li.attr("id", distancewithoutkmtext)
})
.catch(function (error) {
alert(error)
})
k++;
仍然,我们还没有完成。这次电话会议的结果仍然是Promise。仍然是异步调用,completeHandler不会在此等待。但我们几乎就在那里。
我们需要生成一个名为Barrier的同步机制。它没什么特别的,只需等待多个异步任务(promises)完成,一次all
完成后,它会执行你想要的代码。但为此,我们需要创建一个这些Promises的数组!
// create array for promises just before the for loop
var promises = []
// add the promise to the array
var promise = getDistanceMatrixAsync(/* data... */).then(/* stuff with the distance */).catch(/*optional error handling*/)
promises.push(promise)
// finally, outside and after the for loop, create a barrier!
Promise.all(promises).then(function() { completeHandler() })
所以这是成功的最短途径!它远非清洁和可维护,但它应该工作。如果您对提高可维护性感兴趣,请打电话给我,我们也可以通过它。
推荐阅读:
编辑:
修正了then
getDistanceMatrixAsync
中ID的错误。请注意,由于Promise解决方案无法到达,因此它会更改li
标记的ID编号逻辑。我建议使用代理ID,即与应用程序中的任何逻辑无关的ID(目前您在列表中使用位置,这会导致耦合)