javascript - convert - node callback to async await




JavaScriptが戻り値を待っていないようです (3)

私は...私が書いてきたコードが非同期的に動いているという印象を受けています。

はい、そうです。 Googleコールの完了前に関数が返されるため、 geocode関数は呼び出しの結果をGoogle APIに返すことはできません 。 以下の注意を参照してください。

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関数を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();
    }
});

たとえば、 完全に非同期になります。

私はこれとしばらくの間闘ってきました。 私はJavascriptが新しく、私が書いてきたコードが非同期で実行されているという印象を受けています。 一般的な例を次に示します。

私は関数でいくつかのコードを実行します。 関数Aは関数Bを呼び出します。関数Bは変数をAに戻す必要があるため、Aは後の操作で変数を使用することができます。 しかし、AがBを呼び出すと、戻り値のブロックを待つことなく、独自のコードを実行し続け、Bは、Aが戻り値を使用する必要があったポイント値と私は未定義の変数型のエラーを取得します

私はこれを回避している方法は、関数Aコール関数Bを持っていますが、その後、戻り値でやっているであろう後の操作を行う関数Cを呼び出します。私はコールを使って自分のコードをシリアライズしています返品の代わりに...それは面倒ですが...

実際のコードで起こったときの例を次に示します。

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

注意: initializeは、私のhtmlのbody onload = "initialize()"によって呼び出されます。

問題は、makeMapにはGeocode関数で取得した緯度と経度の値が必要ですが、結果が定義されていないというエラーがコンソールに表示されます。 何が起こっている? 私はJavaから来たので、ここではJSでデータの流れがどのように起こっているのか少し混乱しています! これは将来の貴重な教訓になるでしょう!

側面の質問:外部スクリプト間で関数をどのように分割すればよいですか? 良い練習とは何か? 私のすべての機能は1つの外部.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);
        }
   });

}

...

確かに、呼び出しが非同期であり、適切な戻り値が得られていないことを正しく認識しています。

通常、関数が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);
}




asynccallback