我正在做一个个人项目,却被困在似乎是“基本”同步/异步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 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*/ );


显示的结果是:


  距离[在此处插入LAST currentLandmarkName] 5公里
  距[在此处插入LAST currentLandmarkName] 8.5公里
  距离[在此处插入LAST currentLandmarkName]这里0.2公里


而应该是:


  距离[在此处插入第一个currentLandmarkName] 5公里
  距离[在此处插入SECOND currentLandmarkName] 8.5公里
  距离[在此处插入第三个currentLandmarkName] 0.2公里


我不明白的是,当我写console.log(loadedLandmarks)时,数组的内容是正确的,其中loadedLandmarks[0].Name =名字,loadedLandmarks[1].Name =第二名字,依此类推。
但是,i始终等于3,并且currentLandmarkName始终等于最后一个地标名称。
看来它们被覆盖了,我不明白为什么。


我是JS和异步问题的新手,有人可以向我解释为什么我会遇到这种行为,并且非常重要的是,如何纠正它?

最佳答案

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();

09-07 03:54