Javascript 在循环中调用时如何显示JS异步结果?
我正在做一个个人项目,我被困在一个“基本”的同步/异步Javascript问题上 总之,我调用一个异步API,然后在屏幕上显示结果。Javascript 在循环中调用时如何显示JS异步结果?,javascript,asynchronous,formatting,synchronous,Javascript,Asynchronous,Formatting,Synchronous,我正在做一个个人项目,我被困在一个“基本”的同步/异步Javascript问题上 总之,我调用一个异步API,然后在屏幕上显示结果。 格式化后的预期结果是:“距离Y X公里处”,其中X是从API计算并正确返回的,Y是位置的名称(未正确显示) 这是我的代码,为了更好地理解,这里有一些注释: //loadedLandmarks.length is **always** between 1 and 3. No exception. //In this sample, let's say we have
格式化后的预期结果是:“距离Y X公里处”,其中X是从API计算并正确返回的,Y是位置的名称(未正确显示) 这是我的代码,为了更好地理解,这里有一些注释:
//loadedLandmarks.length is **always** between 1 and 3. No exception.
//In this sample, let's say we have 3 items in loadedLandmarks
for(var i = 0 ; i < loadedLandmarks.length ; i++)
{
var currentLandmarkName = loadedLandmarks[i].customInfo.Name;
landmarksName.push(loadedLandmarks[i].customInfo.Name);
//landmarkName contains the good names, for example : "My school", "My home", "My favorite nightclub" (here after 3 pass on the loop)
console.log(landmarksName);
//DisplayDistanceFromLandmarks is my method which calls the asynchronous API. It seems OK.
DisplayDistanceFromLandmarks(pos, i).then(function(response) {
//The response variable contains correct informations from the API
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
var results = response.rows[0].elements;
//I explain this line below
console.log(loadedLandmarks)
//Then I'm formatting the result to display it on screen (I only paste here the interesting part)
distances += "<br />At " + results[0].distance.value + "kms from" + currentLandmarkName;
return distances;
}).done( /*some other things*/ );
//loadedLandmarks.length始终**在1和3之间。也不例外。
//在这个示例中,假设我们在loadedLandmarks中有3项
对于(变量i=0;i 在“+结果[0]。距离.value+”公里距离“+currentLandmarkName;
返回距离;
}).完成(/*一些其他事情*/);
显示的结果如下:
距离[在此插入最后一个currentLandmarkName]5公里处距离[在此插入最后一个currentLandmarkName]8.5公里处
距离[在此插入最后一个currentLandmarkName]0.2公里处 鉴于它应该是: 距离[在此插入第一个currentLandmarkName]5公里处
距离[在此插入第二个currentLandmarkName]8.5公里处
距离[在此插入第三个currentLandmarkName]0.2公里处 我不明白的是,当我编写
console.log(loadedLandmarks)
时,数组的内容是正确的,带有loadedLandmarks[0]。Name
=第一个名字,loadedLandmarks[1]。Name
=第二个名字等等。
但是,i
始终等于3,currentLandmarkName
始终等于最后一个LandmarkName。看起来它们被覆盖了,我不明白为什么
我对JS和异步问题非常陌生,有人能解释我为什么会遇到这种行为,以及,非常重要的,如何纠正它吗?这个方法
displaydestancefromlandmarks
是异步的,这意味着它不会阻止其余的代码执行。所以当你在ca中形成html字符串distance
时我也这么说:
distances += "<br />At " + results[0].distance.value + "kms from" + currentLandmarkName;
我觉得你可以做两件事:
currentLandmarkName
传递到DisplayDistanceFromLandmarks
方法中,从而将其纳入范围i
。这样,您就强制异步行为是同步的。因此,只有在解析承诺并评估回调后,才会进行下一次循环迭代DisplayDistanceFromLandmarks(pos,i)的函数中,然后()
使用变量currentLandmarkName
,这会给您带来一些麻烦
该变量不是在该函数内部定义的,而是在该函数外部的循环中定义的:
for(var i = 0 ; i < loadedLandmarks.length ; i++)
{
var currentLandmarkName = loadedLandmarks[i].customInfo.Name;
...
i
等于加载的地标。长度-1
因此,当调用then
函数时,它会尝试访问始终等于最后一个元素的currentLandmarkName
引用:
loadedLandmarks[loadedLandmarks.length-1].customInfo.Name;
因此,您总是会得到[在此处插入最后一个currentLandmarkName]
var i=0;
var i = 0;
var DisplayDistance = function () {
var currentLandmarkName = loadedLandmarks[i].customInfo.Name;
landmarksName.push(loadedLandmarks[i].customInfo.Name);
//landmarkName contains the good names, for example : "My school", "My home", "My favorite nightclub" (here after 3 pass on the loop)
console.log(landmarksName);
//DisplayDistanceFromLandmarks is my method which calls the asynchronous API. It seems OK.
DisplayDistanceFromLandmarks(pos, i).then(function(response) {
//The response variable contains correct informations from the API
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
var results = response.rows[0].elements;
//I explain this line below
console.log(loadedLandmarks)
//Then I'm formatting the result to display it on screen (I only paste here the interesting part)
distances += "<br />At " + results[0].distance.value + "kms from" + currentLandmarkName;
i++;
if (i < loadedLandmarks.length) {
DisplayDistance();
}
return distances;
}).done( /*some other things*/ );
}
DisplayDistance();
var DisplayDistance=函数(){
var currentLandmarkName=loadedLandmarks[i].customInfo.Name;
LandmarkName.push(loadedLandmarks[i].customInfo.Name);
//landmarkName包含好名字,例如:“我的学校”、“我的家”、“我最喜欢的夜总会”(在循环3次之后)
console.log(landmarksName);
//DisplayDistanceFromLandmarks是我调用异步API的方法,看起来还可以。
显示与地标的距离(位置,i)。然后(功能(响应){
//响应变量包含来自API的正确信息
var origins=response.originAddresses;
var destinations=response.destinationaddress;
var results=response.rows[0]。元素;
//我在下面解释这一行
console.log(加载的地标)
//然后我将格式化结果以在屏幕上显示它(我只在这里粘贴有趣的部分)
距离+=“
在“+结果[0]。距离.value+”公里距离“+currentLandmarkName;
i++;
如果(i<加载的地标长度){
显示距离();
}
返回距离;
}).完成(/*一些其他事情*/);
}
显示距离();
我只是复制/粘贴了你建议的修改,效果非常好,非常感谢!!用你的代码进行一些解释可能会更好,但我会尝试用其他答案来理解。再次感谢Hanks的解释
loadedLandmarks[loadedLandmarks.length-1].customInfo.Name;
var i = 0;
var DisplayDistance = function () {
var currentLandmarkName = loadedLandmarks[i].customInfo.Name;
landmarksName.push(loadedLandmarks[i].customInfo.Name);
//landmarkName contains the good names, for example : "My school", "My home", "My favorite nightclub" (here after 3 pass on the loop)
console.log(landmarksName);
//DisplayDistanceFromLandmarks is my method which calls the asynchronous API. It seems OK.
DisplayDistanceFromLandmarks(pos, i).then(function(response) {
//The response variable contains correct informations from the API
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
var results = response.rows[0].elements;
//I explain this line below
console.log(loadedLandmarks)
//Then I'm formatting the result to display it on screen (I only paste here the interesting part)
distances += "<br />At " + results[0].distance.value + "kms from" + currentLandmarkName;
i++;
if (i < loadedLandmarks.length) {
DisplayDistance();
}
return distances;
}).done( /*some other things*/ );
}
DisplayDistance();