web-dev-qa-db-ja.com

jQuery 1.8.xで一連の遅延関数をチェーンするにはどうすればよいですか?

これらの機能を考えると:

function func1() {
  var dfd = $.Deferred();

  setTimeout(function() {
    dfd.resolve('Password');
  }, 1000);

  return dfd.promise();
}

function func2(message) {
  var dfd = $.Deferred();

  setTimeout(function() {
    if (message == 'Password') {
      dfd.resolve('Hello World');
    }
   }, 1000);

  return dfd.promise();
}

次のことを行うためのより良い方法を見つけたいと思います。これはjQuery1.8.xを使用していることに注意してください。

var promise = func1();

promise.done(function(message1) {

  var promise2 = func2(message1);

  promise2.done(function(message2) {
    alert(message2);
  });
});

何か案は? jQueryの#pipeまたは#thenを使用すると機能すると思いましたが、理解できません。これが遊んでいるフィドルです: http://jsfiddle.net/Z7prn/

18
camwest

それほど複雑ではありません(.thenまたは.pipeを使用します。どちらも、jQuery 1.8以降同じだと思います)。

func1().then(func2).done(function(message) {
    alert(message);
});

func2は新しい遅延オブジェクトを返すため、代わりに.doneコールバックがそのオブジェクトにアタッチされます。

[〜#〜]デモ[〜#〜]

38
Felix Kling

私も同様のユースケースを持っていたので、これはあなたを助けるはずだと思います。

次のメソッドは、一連のメソッド(Promisesを返す場合と返さない場合があります)を受け取り、それらを順番に実行し、各遅延が完了するまで待ってから続行します。デフォルトの動作は、失敗時に停止することです。 2番目の引数を使用すると、呼び出しが失敗したかどうかに関係なく続行できます。

完了/失敗ハンドラーの署名は(Array <context>)関数(Array <Object {拒否|解決済み:引数}>)、ここでcontextは、各resolveWith/requireWith呼び出し、または問題の延期のコンテキストであり、 argumentsは、解決/拒否で渡された引数セットです。

(function ($) {
    "use strict";
    var copy = function (a) {
        return Array.prototype.slice.call(a);
    };

    /**
        Handle a sequence of methods, stopping on failure by default
        @param Array<Function> chain    List of methods to execute.  Non-deferred return values will be treated as successful deferreds.
        @param Boolean  continueOnFailure   Continue executing even if one of the returned deferreds fails.
        @returns Deferred
     */
    $.sequence = function (chain, continueOnFailure) {
        var handleStep, handleResult,
            steps = copy(chain),
            def = new $.Deferred(),
            defs = [],
            results = [];
        handleStep = function () {
            if (!steps.length) {
                def.resolveWith(defs, [ results ]);
                return;
            }
            var step = steps.shift(),
                result = step();
            handleResult(
                $.when(result).always(function () {
                    defs.Push(this);
                }).done(function () {
                    results.Push({ resolved: copy(arguments) });
                }).fail(function () {
                    results.Push({ rejected: copy(arguments) });
                })
            );
        };
        handleResult = continueOnFailure ?
                function (result) {
                    result.always(function () {
                        handleStep();
                    });
                } :
                function (result) {
                    result.done(handleStep)
                        .fail(function () {
                            def.rejectWith(defs, [ results ]);
                        });
                };
        handleStep();
        return def.promise();
    };
}(this.jQuery));

簡単な使用例: http://jsfiddle.net/rG9rA/

function func1() {
  var dfd = $.Deferred();

  setTimeout(function() {
    dfd.resolve('Password');
  }, 1000);

  return dfd.promise();
}

function func2(message) {
  var dfd = $.Deferred();

  setTimeout(function() {
    if (message == 'Password') {
      dfd.resolve('Hello World');
    }
   }, 1000);

  return dfd.promise();
}

    $.sequence([func1, func2, function () { alert('done'); }]);
5
Fordi