1

一部のコードが処理された後、グローバル変数に値を与えようとしています。計画どおりに機能していません。

私がやっていることは、2 つのテキストボックスに住所と都市を入力することです。最後の関数に入り、アドレスの座標を取得する codeAddress を呼び出します。

そこから座標を setLatLng に送信すると、正常に動作します。しかし、getLatLng を使用して longlats を呼び出して設定値を確認することはできません。

住所と都市を 2 回追加した場合にのみ、値が表示されます。longlats の初期化が遅すぎて、正しい値が間に合わないと考えています。

何かアドバイス?

関連するコードは以下です。

<script>
var longlats ="";

function setLatLng(x,y){
    longlats = x+","+y;
    alert(longlats) //shows value
}

function getLatLng(){
    alert(longlats);
    return longlats;
    //calling this gives undefined
}

function codeAddress() {

$('#map').show();
var geocoder = new google.maps.Geocoder();
var address = document.getElementById("address").value +"," + document.getElementById("city").value;

geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
    var lat = results[0].geometry.location.lat();
    var lng = results[0].geometry.location.lng();
    locationsall[counter] = new Array();
    locationsall[counter][0] = address;
    locationsall[counter][1] = lat; //has value
    locationsall[counter][2] = lng; //has value
    setLatLng(locationsall[counter][1],locationsall[counter][2]);

counter++;

} 

$(function() {
$("#locationadd").click(function() {
   codeAddress();
   var get = getLatLng();//value is undefined..
  //i want to do stuff with the values in longlats
}
)};

</script>

編集1

 $("#locationadd").click(function() {
var address = $("#address").val();
var city = $("#city").val();

if (address =="" || city =="") {
    $("#locationtext").text('*Please enter an address and city');
    return false;
} 
else {
    codeAddress(function(){
    var get = getLatLng();
    var longlat = get.split(",");
    var lat = longlat[0];
    var lng = longlat[1];

    var $tr2 = $('<tr>').css({
            'padding': '4px',
            'background-color': '#ddd'
    }).appendTo('#locationDeals');

    var location = [
            address,
            city
    ];
    locations.push(location);

    for (i = 0; i < 2; i++) {
        var $td2 = $('<td>').appendTo($tr2);
        $('<span>').text(location[i]).appendTo($td2);
        $('<input type="hidden">').attr({
            'name': 'loc[' + ctr + '][' + i + ']',
            'value': location[i]
        }).appendTo($td2);
    }
    var $tdRemoveRow2 = $('<td>').appendTo($tr2);
    $('<a>').attr({
        'href': '#',
        'id': 'submit-button'
    }).text("Remove").click(function() {
    var index2 = $tr2.index();
    $("#locationDeals input[type='hidden']").each(function() {
        this.name = this.name.replace(/\[(\d+)\]/, function(str2, number2) {
          return "[" + (+number2 > index2 - 1 ? number2 - 1 : number2) + "]";
        });
    });

    $tr2.remove();
    var tmp = locations.splice(locations.indexOf(location), 1);
    deleteMarker(tmp);
    return false;
    }).appendTo($tdRemoveRow2);

    ctr++;
    document.getElementById("address").value = "";
    document.getElementById("city").value = "";
    document.getElementById("address").focus();
    $("#locationtext").text('');

    return false;
    });
    } 
});
4

3 に答える 3

3

問題はgeocoder.geocode非同期です。codeAddress関数が設定される前に戻るため、あなたのやり方ではできませんlonglats。Google マップが結果を返した後でのみ、longlats を使用するようにコーディング スタイルを変更する必要があります。

これからコードを変更する必要があります。

$("#locationadd").click(function() {
   codeAddress();
   var get = getLatLng();//value is undefined..
  //i want to do stuff with the values in longlats
}

これに:

$("#locationadd").click(function() {
   codeAddress(function(){
     var get = getLatLng();
     //do stuff with the values in longlats
   });
});

そのためには、次のように変更する必要がありますcopyAddress

function codeAddress(callback) {

  /*
   * Some stuff
   */

  geocoder.geocode( { 'address': address}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      /*
       * Some stuff
       */

      setLatLng(locationsall[counter][1],locationsall[counter][2]);

      callback(); // This is where/when the values are returned
                  // so this is where/when we want to execute code.  
    } 
  })
}

追加説明:

あなたのコメントから、あなたはまだこれをやろうとしているようです:

var val;
codeAddress(function(){
    val = getLatLng();
});
doStuffWith(val);

getLatLng が実行される前に codeAddress が返されるため、これは機能しません。コーディングのスタイルを変更する必要があります。次のように記述する必要があります。

codeAddress(function(){
    val = getLatLng();
    doStuffWith(val);
});

つまり、codeAddress の呼び出し後に記述したすべてのコードを関数 INSIDE codeAddress に移動する必要があります。

その理由は、コードの実行方法が次のようなものだからです。

  • ブラウザが JAVASCRIPT フェーズに入る:

       codeAddress is called
              |
              |
              |--------------> inside codeAddress a request to google maps
              |                is made which registers a callback function
              |                to be executed once it returns.
              v
       codeAddress returns
       note that at this point getLatLng isn't called yet
       this is because the browser haven't made the request
       to google maps yet because it's still executing the
       javascript engine.
              |
              v
       code written after codeAddress is executed
       (remember, the call to google maps still haven't happened yet)
              |
              v
       no more javascript to execute
    
  • javascript フェーズが終了し、ブラウザが DOM レンダリング フェーズに入る

       The DOM gets updated and drawn on screen if there are any changes.
    
  • DOM レンダリングが終了し、ブラウザがネットワーク フェーズに入る

       (note: in reality the network layer is asynchronous)
    
       Browser executes pending requests (images, iframes, XMLHttprequest etc.)
       Makes the necessary network connections and begins downloading stuff.
              |
              |
              v
       Browser services completed requests and schedules appropriate events
       (update DOM, trigger onreadystatechange etc.)
       Note that at this point no javascript or DOM updates actually happens.
       The browser does things in a loop, not recursively.
       It is at this point that the google maps request is made.
              |
              v
       No more network operations to service
    
  • ネットワーク フェーズが終了し、ブラウザが JAVASCRIPT フェーズに入る

       google maps request completes, onreadystatechange executes
              |
              |
              |----> inside onreadystatechange the callback to the
              |      google maps API is called
              |             |
              |             '-----> inside the google maps callback getLatLng
              |                     is called, then the callback to codeAddress
              |                     is called.
              |                          |
              |                          '------> inside the callback to
              |                                   codeAddress you can now
              |                                   use the returned values.
              |                                   This is the reason you need
              |                                   to move all your code here.
              v
       no more javascript to execute
    
  • javascript フェーズが終了し、ブラウザが DOM レンダリング フェーズに入る

イベントループが続きます。

ご覧のとおり、単純に codeAddress から値を返すことはできません。代わりに、適切なタイミングで実行されるように、コードを codeAddress 内に移動する必要があります。

于 2012-11-09T02:26:46.490 に答える
0

の値をundefined呼び出すときにまだ設定されていないために取得します。getLatLng()longlats

関数codeAddress()は非同期リクエストを行うため、引数としてコールバックを受け入れることができるようにする必要があります。

codeAddress(function(longLat){
    // do something with longLat
}); 

関数codeAddressを宣言するときは、必ずコールバックを実行し、longLat値を渡してください。

この他の答えを確認してください

于 2012-11-09T02:19:39.860 に答える
0

Googleジオコーディングサービスは、非同期のAJAX呼び出しを行います。呼び出すcodeAddess()と、AJAXリクエストが発生し、すぐに戻ります。応答はまだ受信されていないため、変数は設定されていませんが、getLatLng()とにかく空のアラートボックスが表示された状態で応答を取得しようとしています(おそらく)。やりたいことは、ジオコーディング関数にコールバックを渡し、そこで後続の作業を行うことです。例えば、

function codeAddress(fn) {
   /* Code here */
   if (status == google.maps.GeocoderStatus.OK){
     /* More code here */
     /* Call callback in the end or after setting*/
     fn();
  }
}

次のように設定できます。

$("#locationadd").click(function() {
   codeAddress(getLatLng);
});
于 2012-11-09T02:21:14.027 に答える