2012-01-10 10 views
2

OOスタイルでJavascriptを使用しようとしています.1つのメソッドでは、Webページで使用できるようにデータを取得するためにリモート呼び出しを行う必要があります。私は他の場所でロジックを再使用できるようにそうように、データ検索をカプセル化するJavaScriptクラスを作成しました:Webページ自体がこのようなを呼び出しjQuery Ajaxメソッドから値を返す

AddressRetriever = function() { 
    AddressRetriever.prototype.find = function(zip) { 
     var addressList = []; 
     $.ajax({ 
      /* setup stuff */ 
      success: function(response) { 
       var data = $.parseJSON(response.value); 
       for (var i = 0; i < data.length; i++) { 
        var city = data[i].City; // "City" column of DataTable 
        var state = data[i].State; // "State" column of DataTable 
        var address = new PostalAddress(postalCode, city, state); // This is a custom JavaScript class with simple getters, a DTO basically. 
        addressList.push(address); 
       } 
      } 
     }); 
     return addressList; 
    } 
} 

は次のとおりです。

$('#txtZip').blur(function() { 
    var retriever = new AddressRetriever(); 
    var addresses = retriever.find($(this).val()); 

    if (addresses.length > 0) { 
     $('#txtCity').val(addresses[0].getCity()); 
     $('#txtState').val(addresses[0].getState()); 
    } 
}); 

問題があります場合によってはaddressesが不可解に空である(すなわち、長さ= 0)ことがあります。 Firebugでは、XHRタブには予想されるデータが返ってくるという応答が表示されます。成功メソッドの内部にアラートを設定すると、長さは正しくなりますが、値を返そうとするとそのメソッドの外になることがあります)空と私のテキストボックスにデータが入力されません。時にはそれが空であると表示されますが、テキストボックスにはとにかく適切に入力されます。

私は別のクラスを取り除き、イベントハンドラにAjaxコール全体を詰め込むことでこれを行うことができますが、これを正しく実行する方法を探していますので、必要に応じて関数を再利用できます。何かご意見は?

+1

可能な複製[jQuery Ajax呼び出しから正しい戻り値を取得できません](http://stackoverflow.com/questions/3537434/cant -get-correct-return-value-from-jquery-ajax-call) –

+0

"error:"ハンドラをインクルードし、successブロック内でaddressListを返す必要があるようです。また、それは非同期であるためです。 AJAX呼び出しが完了する前に "return addressList"が発生している可能性があります。 –

+0

[JavaScript非同期戻り値/ jQueryでの代入]の複製が可能です。(http://stackoverflow.com/questions/7779697/javascript-asynchronous-return-value-assignment-with-jquery) –

答えて

2

簡単に言えば、非同期のajax呼び出しではできません。

通常、Ajaxメソッドは非同期で実行されます。したがって、ajax関数呼び出し自体が返ってくると(コードにreturn addressListがある)、実際のajaxネットワークはまだ完成しておらず、結果はまだ分かっていません。

代わりに、コードの流れをどのように修正し、成功ハンドラまたは成功ハンドラから呼び出す関数でのみajax呼び出しの結果を処理する必要があります。成功ハンドラが呼び出されたときだけ、ajaxネットワークが完成し、結果が返されます。

非同期のajax呼び出しを使用すると、手続き型プログラミングを正常に行うことはできません。コードがどのように構造化され流れているかを変更する必要があります。それは事を複雑にしますが、非同期のajax呼び出しを使用することによるユーザーエクスペリエンスのメリットは巨大です(ブラウザーはネットワーク操作中にロックされません)。ここで

はまだコールバック関数を使用して、かなり一般的なAddressRetriever.find()方法を維持しながら、あなたのコードを再構築でき方法は次のとおりです。すべての

AddressRetriever = function() { 
    AddressRetriever.prototype.find = function(zip, callback) { 
     $.ajax({ 
      /* setup stuff */ 
      success: function(response) { 
       var addressList = []; 
       var data = $.parseJSON(response.value); 
       for (var i = 0; i < data.length; i++) { 
        var city = data[i].City; // "City" column of DataTable 
        var state = data[i].State; // "State" column of DataTable 
        var address = new PostalAddress(postalCode, city, state); // This is a custom JavaScript class with simple getters, a DTO basically. 
        addressList.push(address); 
       } 
       callback(addressList); 
      } 
     }); 
    } 
} 

$('#txtZip').blur(function() { 
    var retriever = new AddressRetriever(); 
    retriever.find($(this).val(), function(addresses) { 
     if (addresses.length > 0) { 
      $('#txtCity').val(addresses[0].getCity()); 
      $('#txtState').val(addresses[0].getState()); 
     } 
    }); 

}); 
+0

コールバックを含めると、Ajaxメソッドを使用できるうちにコードを適切に構造化したままにすることができます。 –

0

不可解ない、リストは時間の不確定量まで満たされることはありません未来。

正式なアプローチは、おそらく独自のコールバックを渡すことによって、成功ハンドラで作業を行うことです。 jQuery's .whenを使用することもできます。

0

AJAX呼び出しは非同期です。つまり、プログラムの通常の流れで実行されません。あなたが実行すると、プログラムが完了するのAJAX呼び出しを待っていなかったとして

if (addresses.length > 0) { 

addresses

は、実際に、空です。

2
AddressRetriever = function() { 
    AddressRetriever.prototype.find = function(zip) { 
     var addressList = []; 
     $.ajax({ 
      /* setup stuff */ 
      success: function(response) { 
       var data = $.parseJSON(response.value); 
       for (var i = 0; i < data.length; i++) { 
        var city = data[i].City; // "City" column of DataTable 
        var state = data[i].State; // "State" column of DataTable 
        var address = new PostalAddress(postalCode, city, state); // This is a custom JavaScript class with simple getters, a DTO basically. 
        addressList.push(address); 
        processAddresss(addressList); 
       } 
      } 
     }); 
    } 
} 

function processAddresss(addressList){ 
    if (addresses.length > 0) { 
     $('#txtCity').val(addresses[0].getCity()); 
     $('#txtState').val(addresses[0].getState()); 
    } 
} 

また、別の関数呼び出しを行いたくない場合は、ajax呼び出しを同期させます。今すぐ、データが配列にプッシュされる前に配列を返しています

+1

この実装は '.find()'をある特定のWebページとそのページ上の特定のオブジェクトにハードワイヤードにします。これにより、AddressRetrieverオブジェクトの有用性が大幅に低下します。コールバック関数を使用すると、データオブジェクトをHTMLから独立させることができ、さまざまな種類のものや多くの異なるページデザインなどにデータを使用させることができます。 – jfriend00

+0

ありがとう、かなり正しい.. まだ学習中です! – redDevil

関連する問題