繁体   English   中英

JavaScript似乎不等待返回值

[英]JavaScript doesn't seem to wait for return values

我一直在努力解决这个问题。 我是Javascript的新手,并且一直认为我写的代码已经异步运行了。 这是一个通用的例子:

我在函数a中运行了一些代码。 函数A然后调用函数B,函数B需要将变量返回给A,因此A可以在以后的操作中使用它。 看来,当A调用B时,它仍然继续运行自己的代码,而不是等待其返回值被阻塞,并且B不够快,使得A最终到达需要使用返回的点值,我得到一个未定义的变量类型错误

我解决这个问题的方法是使用函数A调用函数B然后调用一个函数C,它将执行A将使用返回值执行的后续操作....我有点通过调用序列化我的代码而不是返回......虽然很麻烦......

以下是在实际代码中发生的示例:

function initialize() {
    //Geocode Address to obtin Lat and Long coordinates for the starting point of our map
    geocoder = new google.maps.Geocoder();
    var results = geocode(geocoder);
    makeMap(results[0].geometry.location.lat(), results[0].geometry.location.lng());

}

function geocode(geocoder) {
    //do geocoding here...

    var address = "3630 University Street, Montreal, QC, Canada";
    geocoder.geocode({ 'address': address }, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
           return results;
            }
         else {
            alert("Geocode was not successful for the following reason: " + status);
        }
   });

}

function makeMap(lat, long) {
  //  alert(lat); for debuging
    var mapOptions = {
        center: new google.maps.LatLng(lat, long),
        zoom: 17,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
     map = new google.maps.Map(document.getElementById("map_canvas"),
        mapOptions);
}

注意:我的html中的body onload =“initialize()”会调用initialize。

所以问题是makeMap需要Geocode函数获得的纬度和经度值,但是在控制台中我得到一个错误,说结果是未定义的。 到底是怎么回事? 我来自Java,所以我对JS中数据流的发生方式感到有些困惑! 这将是未来的宝贵经验!

关于一个问题:我应该如何在外部脚本之间拆分我的功能? 什么是好习惯? 我的所有功能都应该塞进一个外部.js文件中,还是应该将功能组合在一起?

您似乎对问题有了很好的理解,但听起来您并不熟悉解决问题的方法。 解决此问题的最常见方法是使用回调。 这基本上是等待返回值的异步方式。 以下是您在案例中如何使用它:

function initialize() {
    //Geocode Address to obtin Lat and Long coordinates for the starting point of our map
    geocoder = new google.maps.Geocoder();
    geocode(geocoder, function(results) {
        // This function gets called by the geocode function on success
        makeMap(results[0].geometry.location.lat(), results[0].geometry.location.lng());        
    });
}

function geocode(geocoder, callback) {
    //do geocoding here...

    var address = "3630 University Street, Montreal, QC, Canada";
    geocoder.geocode({ 'address': address }, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            // Call the callback function instead of returning
            callback(results);
        } else {
            alert("Geocode was not successful for the following reason: " + status);
        }
   });

}

...

我...的印象是我写的代码一直在异步运行。

是的,它确实。 您的geocode功能无法将调用结果返回给Google API,因为该功能会在Google调用完成之前返回。 见下面的注释:

function geocode(geocoder) {
    //do geocoding here...

    var address = "3630 University Street, Montreal, QC, Canada";
    geocoder.geocode({ 'address': address }, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
           // +---------- This doesn't return anything from your
           // v           geocode function, it returns a value from the callback
           return results;
            }
         else {
            alert("Geocode was not successful for the following reason: " + status);
        }
   });
}

相反,您必须编写geocode功能的代码,以便它接受一个回调,当它有结果时它将调用它。 例如:

// Added a callback arg ---v
function geocode(geocoder, callback) {
    //do geocoding here...

    var address = "3630 University Street, Montreal, QC, Canada";
    geocoder.geocode({ 'address': address }, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
           // v---------- Call the callback
           callback(results);
            }
         else {
            alert("Geocode was not successful for the following reason: " + status);
            callback(null); // <--- Call the callback with a flag value
                            // saying there was an error
        }
   });
}

然后,而不是像这样使用它:

var results = geocode(someArgHere);
if (results) {
    doSomething(results);
}
else {
    doSomethingElse();
}

你这样称呼它:

geocode(someArgHere, function() {
    if (results) {
        doSomething(results);
    }
    else {
        doSomethingElse();
    }
});

例如,你完全异步。

匿名函数内的return语句从匿名函数返回,而不是从外部地理编码函数返回。 地理编码函数返回undefined。 geocoder.geocode方法可以在需要,同步或异步时调用匿名函数。 检查文档。

实际上,您正确认为调用是异步的,并且您没有获得正确的返回值。

通常,当在js中调用函数时,它们是同步的。

e.g. a() calls b(), and a() waits until b() to finish before continuing.

但是,在某些情况下,例如进行ajax或jsonp调用,它是异步完成的。 这正是调用geocode()时发生的情况。

你的执行:

initialize() is called;
initialize() calls geocoder();
geocoder makes a request to Google, and returns null in the meantime.
initialze() calls makemap()
the Google geocoder returns at some point, and executed the success callback, which you have defined as "return results;", but there is nothing to return, since the function has already ended.

因此,具体而言,利用已构建到地理编码器调用中的回调:

if (status == google.maps.GeocoderStatus.OK) {
    makeMap(results);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM