72

同期的に行う必要がある 3 つの HTTP 呼び出しがあり、ある呼び出しから別の呼び出しにデータを渡すにはどうすればよいですか?

function first()
{
   ajax()
}

function second()
{
   ajax()
}

function third()
{
   ajax()
}


function main()
{
    first().then(second).then(third)
}

私は 2 つの関数に deferred を使用しようとしましたが、部分的な解決策を思いつきました。3つの関数に拡張できますか?

function first() {
    var deferred = $.Deferred();
     $.ajax({

             "success": function (resp)
             {

                 deferred.resolve(resp);
             },

         });
    return deferred.promise();
}

function second(foo) {
     $.ajax({
            "success": function (resp)
            {
            },
            "error": function (resp)
            {
            }
        });
}


first().then(function(foo){second(foo)})
4

9 に答える 9

89

いずれの場合も、 によって返された jqXHR オブジェクトを返し$.ajax()ます。

これらのオブジェクトは Promise と互換性があるため、 // .then()/でチェーンできます。.done().fail().always()

.then()質問とまったく同じように、この場合に必要なものです。

function first() {
   return $.ajax(...);
}

function second(data, textStatus, jqXHR) {
   return $.ajax(...);
}

function third(data, textStatus, jqXHR) {
   return $.ajax(...);
}

function main() {
    first().then(second).then(third);
}

Arguments datatextStatusおよび前の関数の呼び出しjqXHRから発生します。フィードとフィード.$.ajax()first()second()second()third()

デモ($.when('foo')の代わりに、約束を果たすために$.ajax(...))。

于 2013-04-16T19:43:55.817 に答える
40

jQuery で promise を使用する場合、実際にはもっと簡単な方法があります。以下をご覧ください。

$.when(
    $.ajax("/first/call"),
    $.ajax("/second/call"),
    $.ajax("/third/call")
    )
    .done(function(first_call, second_call, third_call){
        //do something
    })
    .fail(function(){
        //handle errors
    });

すべての呼び出しを $.when(...) 呼び出しにチェーンし、.done(...) 呼び出しで戻り値を処理するだけです。

必要に応じて、次のウォークスルーをご覧ください: http://collaboradev.com/2014/01/27/understanding-javascript-promises-in-jquery/

于 2014-01-27T23:21:00.557 に答える
15

それよりもはるかに簡単です。

$.ajaxすでに promise (Deferred オブジェクト) を返しているため、単純に次のように記述できます。

function first() {
    return $.ajax(...);
}
于 2013-04-16T00:47:16.180 に答える
6

より機能的な方法で書くことができます:

[function() { return ajax(...)}, function(data) { return ajax(...)}]
.reduce(function(chain, callback) { 
  if(chain) { 
    return chain.then(function(data) { return callback(data); });
  } else {
    return callback();
  }
}, null)
于 2016-01-26T15:48:49.877 に答える
4

ここで見栄えの良い解決策を見つけました: How do I chain a sequence of deferred functions in jQuery 1.8.x?

そして、これは同様のアプローチの私自身の実装です。やや醜いですが、おそらく機能しています。返された promise オブジェクトの «progress update» として各メソッドの結果をブロードキャストします。

  $.chain = function() {
      var defer = $.Deferred();
      var funcs = arguments;
      var left = funcs.length;
      function next(lastResult) {
          if(left == 0) {
              defer.resolve();
              return;
          }
          var func = funcs[funcs.length - left]; // current func
          var prom = func(lastResult).promise(); // for promise will return itself,
                                       // for jquery ojbect will return promise.
          // these handlers will be launched in order we specify them
          prom.always(function() {
              left--;
          }).done(function(ret) {
              defer.notify({
                  idx: funcs.length-left,
                  left: left,
                  result: ret,
                  success: true,
              });
          }).fail(function(ret) {
              defer.notify({
                  idx: funcs.length-left,
                  left: left,
                  result: ret,
                  success: false,
              });
          }).always(function(ret) {
              next(ret);
          });
      }
      next();
      return defer.promise();
  };

状況に応じてどのように使用しますか?美しくないかもしれませんが、うまくいくはずです:

function first() {
    return ajax(...);
}

var id;

funciton second() {
    return ajax(id, ...);
}

function third() {
    return ajax(id, ...);
}

$.chain(first, second, third).progress(function(p) {
    if(p.func == first)
        id = p.result.identifier;
}).then(function() {
    alert('everything is done');
});

または、その id 変数を関数から割り当てることもできfirstます。

または、前の関数の結果のみが必要な場合は、次のアプローチを使用できます。

function first() {
    return ajax(...);
}
function second(first_ret) {
    return ajax(first_ret.id, ...);
}
function third(second_ret) {
    return ajax(second_ret.something, ...);
}
于 2015-09-23T00:33:04.760 に答える