1

私は1週間前に同様の質問をしましたが、私の問題に対する実際の答えはありませんでした。それは私が自分の問題を明らかにした方法によるものです。

私はjquerygooglemapプラグインを書いているので、次のようなことができます:

var my_map = $('#map').plugin();
my_map.addMarker( 'Melbourne, Australia' );
my_map.addMarker( 'New York, USA' );
console.log ( my_map.getMarkers() );  // how to return markers array here ?

マーカーを追加するには、住所を緯度と経度に変換するgooglegeocodeを使用します。応答を受け取ったら、マーカーをマップに追加して配列に保存します。

それはすべて正常に機能しています。マーカー配列を取得するために、プラグインでこれを実行しました。

self.getMarkers = function()
{
    self._deferred.done( function()
    {
        // I need to pass this to the outer scope
        console.log( 'Deferred done :' , self.markers ); 
        return self.markers;
    });
 }

self.markers使用せずに戻っただけdeferredでは、応答がまだ戻っていないため配列は空になりますが、使用するdeferredと、配列を外部スコープに渡すことができません。

また、プラグインを使用している開発者がこれを行う必要はありません:

my_map.done( function( markers ) {
   // code
});

約束を返すことでそれを行うことができますが、行うだけでマーカー配列を取得したいと思いますmy_map.getMarkers()

問題が明確であることを願っています。そうでない場合は、説明を求めてください。完全なコードを確認する必要がある場合は、ここにあります:http: //jsfiddle.net/Vy4da/

4

2 に答える 2

1

これは、非同期コードがどのように機能するかではありません。非同期呼び出しを行う場合に呼び出すmy_map.getMarkers()とき、それがいつ完了し、その呼び出しの「後」のコードにアクセスできるかを絶対に保証することはできません。どういうわけか、これが非同期呼び出しであるという事実を明らかにする必要があります。

私の意見では、最も露出の少ない方法は、ユーザーが次の方法で返された配列を使用するコールバック関数を提供できるようにすることです。

my_map.getMarkers(function (array) {
    //do stuff with returned array here
});

そのコールバック関数をにバインドできます.done。ただし、約束自体を返すことで、より柔軟性が得られると思います。私はあなたが両方を行うことができると思います。

于 2013-02-06T03:15:42.550 に答える
1

コメントに基づいて、少なくとも2つのオプションがあります。

は実際にはすでに発生したものに対してデータ処理を行う同期呼び出しであるため、非同期getMarkers()である状況を処理するだけで済みaddMarker()ます。そして、ここで行う必要があるのは、マーカーの追加が完了していることを確認することだけです。例えば:

// For this to work, you need to put return statements at the start of addMarker and
// placeMarker so that they return the promises they are making

$.when(my_map.addMarker("Melbourne"), my_map.addMarker("New York, USA"))
.then(function()
{
   // a synchronous my_map.getMarkers() is safe to use here
   // just return self._Markers.markers;
});

ご覧のとおり、唯一の難しさは、addMarkerイベントを並列化し、getMarkersすべてが完了したときにのみ使用することです。開発者にとって使いやすいように、プラグインのこの部分を作成することをお勧めします。

self.addMarkers = function( /*...*/ ) // accept array of location or comma separated list
{
    var args = [].concat(Array.prototype.slice.call(arguments));
    return $.when.apply(null, args.map(self.addMarker, self));
}

使用法:

my_map.addMarkers('Melbourne, Australia', 'New York, USA')
.then(function()
{
   console.log(my_map.getMarkers()); // works if synchronous
   console.log(my_map._Markers.markers); // also works
});

実際の動作をご覧ください:http://jsfiddle.net/Vy4da/1/

2番目のオプションは、リクエストが行われた後、元のリクエストオブジェクトとは別の評価オブジェクトを返すことです。これは、JqueryでAJAXによって使用されるパターンです。オプションをに渡してから、でチェーンします。ここで、は結果を評価できる評価オブジェクトであり、おそらく最も関心のある部分です(jqXHR.responseText)。あなたの場合に同じパターンを使用するには、はまったく存在しませんが、代わりにマップリクエスト関数によって解決された構築されたオブジェクトにアタッチされます。このアプローチは、Promiseで解決された場合を除いて定義されていないため、開発者が利用可能になる前に誤って使用することを防ぎます。my_map$.ajaxdone(function(data,status,jqXHR){...})jqXHRdatagetMarkers()my_mapgetMarkers()


元の回答 (getMarkersが非同期であるという誤解に基づく)

が任意の種類の非同期リクエストである場合my_map.getMarkers()、それを同期変数の割り当てとして扱うことはできません。

したがって、非同期呼び出しの結果が含まvar a = my_map.getMarkers()れることはありません。

代わりにpromiseを返す場合は、この呼び出しを他の非同期呼び出しと並列化する方法を決定するオプションを呼び出し元に付与します。

my_map.getMarkers().done( function( markers ) { });は、非同期呼び出しでありながら、同期のような制御ロジックを示すスタイルでコードを記述できるため、これに対するより洗練されたソリューションの1つです。また、エラー状態を好きなように処理することもできます。

最初は面倒だと思いますが、それは非同期プログラミングの現実にすぎません。

于 2013-02-06T06:06:04.543 に答える