2

コンボ ボックスに select2 jQuery ベースの置換を使用しています。jsonレスト Web サービスから受け取ったデータを処理するためのコールバックを定義する必要があります。

問題は、同じコールバックで、一致するレコードの総数を取得するために別の GET 要求を発行する必要があるため、select2 がさらに結果をロードする必要があるかどうかを判断できることです (無限スクロール機能があります)。

コードは次のようなものです。

$("#country").select2({
  ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
    url: 'http://localhost:9000/api/countries',
    dataType: 'json',
    data: function(term, page) {
      return {
        filter: term,
        page: page,
        len: 10
      };
    },
    results: function(data, page) {
      return {
        results: data, more: ????
      };
    }
  }
});

問題は、非同期リクエストを発行する方法がわからないことです(クロスドメインリクエストを発行していますが、その場合、非同期はサポートされていないとドキュメントに記載されています)。結果コールバックから戻る前に、それが完了するのを待ちます。

select2 ページの例は次のようになります。

results: function (data, page) {
  var more = (page * 10) < data.total; // whether or not there are more results available
  // notice we return the value of more so Select2 knows if more results can be loaded
  return {results: data.movies, more: more};
}

問題は、私の Web サービスが別のエンドポイントからレコードの総数を返すことです。そのため、次のように別のリクエストを行う必要があります: http: //localhost:9000/api/countries?filter=term

何か案が?

4

3 に答える 3

8

javascriptで非同期コールバックを待つことはできません。実際のコールバックからの非同期応答に基づいて将来のすべての作業を行うには、コードを再構築する必要があります。

複数の連続したajax呼び出しを行う必要がある場合は、最初の呼び出しを発行し、最初のajax呼び出しの成功ハンドラーまたは応答ハンドラーで2番目のajax呼び出しを発行し、2番目の呼び出しの応答ハンドラーで何でも実行しますあなたはデータでやりたいです。

フレームワークを使用していることがわかった場合.select2()。フレームワークでは、結果のコールバックはajax呼び出しが戻る場所です。通常のjQueryajax呼び出しを使用して2番目のajax呼び出しを発行するのはその関数であり、その2番目のajax呼び出しからの成功ハンドラーでは、返された最終的なデータで実行しようとしていることをすべて実行します。返す必要のある時点で最終データがまだないため、結果コールバックの通常の戻り値を使用することはできません。.select2()これは、単一のajax呼び出しのみをサポートするという点での制限にすぎないと思います。これは、組み込みの動作を少し使用できず、独自のコードを使用して結果を自分で適用する必要があることを意味しますが、そうではありません。.select2()

change2つのシリアル化されたajax呼び出しが必要な場合、実際には多くの機能を提供していないように見えるため、イベントを直接フックし、組み込みのajaxのものを使用しないことをお勧めします。

于 2012-08-28T04:00:31.607 に答える
4

select2 のソース コードを調べたところ、最終的にこのソリューションを思いつきました。

var ajax = {
  url: 'http://localhost:9000/api/countries',
  len: 3,
};

$("#country").select2({
  query: function(options) {
    var data = {
      filter: options.term,
      page: options.page,
      len: ajax.len
    };
    $.ajax({
      url: ajax.url,
      data: data,
      dataType: 'json',
      type: 'GET',
      success: function(data) {
        $.ajax({
          url: ajax.url + '/count',
          data: { filter: options.term },
          dataype: 'json',
          success: function(resp) {
            var total = parseInt(resp, 10);
            var more = (options.page * ajax.len) < total;
            options.callback({results: data, more: more});
          }
        });
      }
    });
  },
});

ご覧のとおり、最初のフェッチ (ajax.url) が完了すると、別のリクエスト (ajax.url + '/count') を発行し、この 2 番目のリクエストが完了したときにのみ、options.callback を呼び出し、両方の ajax 呼び出しを効果的にシリアル化します...

実際、select2 のajax 関数には、スロットリングや順不同の応答のドロップなど、より多くの機能があります。それらも移植しましたが、例を複雑にしないために、この応答から除外しました...

于 2012-08-28T07:53:21.163 に答える
0

jfriend00の答え(これは素晴らしいです、ところで)に加えて、基本的にリクエストを同期的に発行することであるfollowginの回避策を見つけました.

誰かが役に立つと思った場合に備えて投稿しています...

var config = {
  url: 'http://localhost:9000/api/countries',
  len: 20,
  term: ''
}
$("#country").select2({
  ajax: { 
    url: config.url,
    dataType: 'json',
    data: function(term, page) {
      config.term = term;
      return {
        filter: term,
        page: page,
        len: config.len
      };
    },
    results: function(data, page) { // parse the results into the format expected by Select2.
      var more = false;
      $.ajax({
        url: config.url + '/count',
        data: { filter: config.term },
        cache: false,
        async: false,
        success: function(resp) {
          var total = parseInt(resp, 10);
          more = (page * config.len) < total;
        },
        async:false
      });
      return {
        results: data, more: more
      };
    }
  }
});
于 2012-08-28T04:32:13.560 に答える