簡體   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