1

Javascript(jQuery)で次のことを行う慣用的な方法は何ですか?

  • 一連の非同期ジョブを生成します
  • 部分的な結果を収集する
  • すべてのジョブが完了したら、部分的な結果を組み合わせる

上記は、次の行で達成できます(簡単にするために、要求が順番に処理されると仮定します。より現実的なケースでは、カウンターがその役割を果たします)。

var results = new Array();
$.each(objs, function(i,obj)){
  $.getJSON(make_async_request(obj), function(data) {
    results[data.key] = data.value;
    if (i == objs.length-1)
      elaborate(results);
  }
});

それは私には醜いように見えます。助言がありますか?

4

5 に答える 5

1

jQuery.Deferred次のように使用できます。

   $.when($.get('/a/'), $.get('/b/')).then(function() {
       // all gets are ready
   });

オブジェクト内のすべての結果をマージする必要がある場合は、thenコールバックで引数をループできます。

$.when($.get('/a/'), $.get('/b/')).then(function() {
    var results = {},
        args = Array.prototype.slice.call(arguments),
        data;
    $.each( args, function(i, resp) {
        data = resp[0];  // resp is the results array
        results[data.key] = data.value;
    });
    console.log(results);
});
于 2012-07-22T16:03:37.933 に答える
0
var results = [], ajaxes = [];
$.each(objs, function(i,obj)){
    var xhr = $.ajax({
        url: make_async_request(obj),
        dataType: 'json'
    }).done(function() {
        results[data.key] = data.value;
        if (i == objs.length-1) elaborate(results);
    });
    ajaxes.push(xhr);
});

$.when.apply(null, ajaxes).done(function() {
    alert('all ajaxes are done');
});
于 2012-07-22T16:14:55.487 に答える
0

ジョブの完了をチェックするのは非同期であるため不十分で$.getJSONあり、リクエストを行った直後に戻ります。そのため、最後のリクエストが行われるとすぐに、チェックはtrueと評価されます。

あなたは事実を利用することによってあなたが望むことを効果的に行うことができます、$.ajaxそしてそれ故にDeferreds$.getJSONを返します。およびを使用して、処理するすべての要求のデータを収集します。jQueryのdefered/promise apiを見てください。これらは非常に強力であり、次のワンライナーのようなものが機能することを可能にします。$.when$.map

$.when($(objs).each(function (i, obj) { return $.getJSON(make_async_request(obj)); }), elaborate);
于 2012-07-22T16:20:40.047 に答える
0

完全な開示:私自身のライブラリの露骨なプラグイン、キューフロー:)

q(objs)
    .map(q.async(function(obj, callback) {
        $.getJSON(make_async_request(obj), callback);
    }))
    .reduce(function(results, data) {
        results[data.key] = data.val;
        return results;
    }, elaborate, {});

queue-flowは、キューの概念を使用して、非同期関数型コードをほぼ完全に同期しているように見せます。:)また、ソースコードの編成で非常に興味深いことを行うことができます.branch。GitHubのreadmeにあるメソッドを見てください。(質問の例の変更に一致するように例を更新しただけです。)

それは次のように書くこともできます:

q(objs)
    .map(make_async_request)
    .map(q.async($.getJSON))
    .reduce(function(results, data) {
        results[data.key] = data.val;
        return results;
    }, elaborate, {});

これは本当にクールですが、なじみのない人がグロクするのに少し時間がかかるかもしれません。:)

于 2012-07-22T21:52:58.463 に答える
0

2018年現在の更新:今では使用できます

results = await Promise.all(objs.map(someAsyncFunction));

ここobjsにいくつかのリストがありsomeAsyncFunction、このリストの1つの要素を取り、結果とともにpromiseを返します。詳細については、この質問への回答を参照してください:マップ内で非同期関数を呼び出すための最良の方法は?

于 2021-04-25T12:46:41.753 に答える