人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

GoogleAPIを利用して、住所から緯度経度を得る関数を作ろうとしています。
下記のようなコードの場合、geocoder.getLatLngが非同期なため、[3]→[1]→[2]の順で実行され、[2]以外のresult['lat']/result['lng']は、undefinedになってしまいます。
この非同期メソッドを上手くフォローした関数にするにはどうすれば良いでしょうか?
(www.geocoding.jpのようなASPもあるようですが、なるべく自前で作りたいため)
result = add2latlng("渋谷区1-1");
alert( "[1]address:" + result['address'] + "/lat:" + result['lat'] + "/lng:" + result['lng'] );

function add2latlng( address ) {
var result = new Array();
geocoder = new GClientGeocoder();
geocoder.getLatLng(address,
function(point) {
result["lat"] = point.lat();
result["lng"] = point.lng();
alert( "[2]address:" + address + "/lat:" + result['lat'] + "/lng:" + result['lng'] );
}
);
result['address'] = address;
alert( "[3]address:" + address + "/lat:" + result['lat'] + "/lng:" + result['lng'] );
return result;
}

●質問者: P-mako
●カテゴリ:インターネット ウェブ制作
✍キーワード:.jp ASP LNG point WWW
○ 状態 :終了
└ 回答数 : 4/4件

▽最新の回答へ

1 ● takonixi
●23ポイント

非同期の処理を同期に変えることはできないかと思いますので

下記のように実行処理の部分を引数で与える形にしてはどうでしょうか?


function add2latlng( address , func ) {

  geocoder = new GClientGeocoder();

  geocoder.getLatLng(address,

    function(point) {

      var result = {};

      result["lat"] = point.lat();

      result["lng"] = point.lng();

      alert( "[2]address:" + address + "/lat:" + result['lat'] + "/lng:" + result['lng'] );

      result['address'] = address;

      alert( "[3]address:" + address + "/lat:" + result['lat'] + "/lng:" + result['lng'] );

      func(result);

    }

  );

}


result = add2latlng(

  "渋谷区1-1",

  function(result){

    //実行する処理

    alert( "[1]address:" + result['address'] + "/lat:" + result['lat'] + "/lng:" + result['lng'] );

  }

);

URLはダミーです

http://q.hatena.ne.jp/

◎質問者からの返答

(XML)HttpRequestオブジェクトのようにreadyStateのような状態監視ができれば良いなぁと思っていたのですが、コールバックハンドラ形式でも工夫次第で解決できるかも知れないですね。

でも、複数の住所を緯度経度に変換して取得したいので、もう少しスマートな方法があればよいんですが・・・

もしくは、上記の下から7行目の result = add2latlng( で、resultに取得できてしまうんでしょうか?

私の知識では意味の無い戻り値だと感じますが・・・

今試せる環境にないので、後で試してみます。


2 ● ardarim
●23ポイント

最後の部分を

result['address'] = address;
while(result['lat'] == undefined && result['lng'] == undefined);
alert( "[3]address:" + address + "/lat:" + result['lat'] + "/lng:" + result['lng'] );
return result;

でどうでしょうか?

非同期からの結果が入るのを待つ感じです。

これで[2]->[3]->[1]の順序になって、3つとも期待通りの値が入ると思います。


urlはダミー

http://q.hatena.ne.jp/1194229236


3 ● takonixi
●22ポイント

すいません 上記のは確かにresultにはreturnしないのではいりませんね

複数でしたら下記のような感じではどうでしょうか?


var add2latlng = function(address, func){

    var geocoder = new GClientGeocoder();

    //全部の処理を終えたか確認

    //終えていればfuncを実行

    var execute = function(){

        for(var i = 0;i < address.length;i++){

            if( !address[i].complete ){

                return ;

            }

        }

        func(address);

    }

    //一つ分取得しexecute実行

    var getLatLng = function(index){

        geocoder.getLatLng(

            address[index]["address"],

            function(point) {

                address[index]["lat"] = point.lat();

                address[index]["lng"] = point.lng();

                address[index].complete = true;        //取得フラグ

                execute();

            }

        );

    }

    //各addressのlat,lng取得関数呼び出し

    for(var i = 0;i < address.length;i++){

        //取得フラグ

        address[i].complete = false;

        //各都道府県データ取得

        getLatLng(i);

    }

};

new add2latlng(

    //形式は{"address":"渋谷区1-1"}の配列形式

    [{"address":"渋谷区1-1"},{"address":"渋谷区2-4"},{"address":"渋谷区3-6"}],

    //実行処理

    function(result){

        for(var i = 0;i < result.length;i++){

            alert( "["+i+"]address:" + result[i]['address'] + "/lat:" + result[i]['lat'] + "/lng:" + result[i]['lng'] );

        }

    }

);


ダミーURLです

http://q.hatena.ne.jp/


4 ● lunlumo
●22ポイント

この変換処理はWebServiceでも公開されているので,サーバサイドで問い合わせて返す処理を用意すれば比較的簡単に同期処理が書けます。コールバック処理でモデルを更新して,モデルからビューに更新を通知すると言った形で処理した方が素直かとは思いますが。

http://code.google.com/apis/maps/documentation/services.html#Geo...

varproxyUrl = "/cgi-bin/google/maps/proxy.cgi";

function add2latlng(address) {
varrequest = new GXmlHttp.create();
varresponse;
varresult = new Array();

request.open("GET", proxyUrl + "?q=" + encodeURI(address), false);
request.send(null);
response = eval("(" + request.responseText + ")");

for (var i = 0;i < response["Placemark"].length;i++) {
varcoordinates= response["Placemark"][i]["Point"]["coordinates"];
result.push({"lat":coordinates[0],"lng":coordinates[1]});
}

return result;
}
関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ