2012-11-30 9 views
16

は、これらの機能を考える:遅延関数のシーケンスを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(); 
} 

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

var promise = func1(); 

promise.done(function(message1) { 

    var promise2 = func2(message1); 

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

私はjQueryを#pipeまたは#を使用して動作すると思ったが、私はそれを把握することはできません。 http://jsfiddle.net/Z7prn/

答えて

34

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

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

func2新しい遅延オブジェクトを返すので、.doneコールバックではなく1つに取り付けられています。

DEMO

+1

人々は、このような簡潔な方法で物事を説明するとき、私は大好きです。理解しやすくするために – tim

+1

注: '.pipe'はjQuery 1.8([docs](http://api.jquery.com/deferred.pipe/))で非推奨になっているので' .then'を使用してください。 – nhylated

-2

使用JQuery.when()。これはまさに遅延配列を連鎖して、すべてが完了したときに関数を実行したいものです。更新2017

(downvotesを見た後):何を望むかOP

は順次約束を実行するために彼のコードの改良版でした。ここに私のバージョンは$.whenを使用している:

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(); 
 
} 
 

 
// ~~~~~~~~~~ using $.when here ~~~~~~~~~~~~ 
 

 
$.when(func1()).then(function(result1) { 
 
    $.when(func2(result1)).then(function(result2) { 
 
     alert(result2); 
 
    }) 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>

+5

連鎖され、それらは収集される。 defersの配列は 'at once'で呼び出され、when()calllbackはすべてで終了します。他の手では()をチェーンすることができますので、func2()などの前にfunc1()を解決する必要があります。 –

+0

@DesignbyAdrian OPの質問をどう解釈するのですか? 投稿されたコードを実行したり、タイトルを読んだり、彼がそれらをチェイスしたいと思ったりするのを見ることができます。彼はちょうど良い方法を使って2番目のスナップを書き直す方法を探しているだけで、それは私が言及したものであり、例を追加しただけです。私のスニペットの出力は3 LOCの彼(望む通り)と同じです。 – Aidin

5

私は類似したユースケースを持っていたので、私は、これはあなたを助けるべきだと思います。

次のメソッドは、Promisesを返す場合と返さない場合がある)メソッドの配列をとり、順番に実行します。処理が進む前に各遅延が完了するまで待機します。デフォルトの動作は失敗時に停止することです。 2番目の引数は、呼び出しが失敗したかどうかにかかわらず処理を続行します。

ハンドラシグネチャが(配列< コンテキスト>)機能(配列<オブジェクト{拒否|解決:引数}>)が失敗/行わコンテキスト各resolveWith/rejectWith呼び出しのコンテキストである、または問題の遅延との引数は解決/拒否で渡された引数セットです。

(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'); }]); 
+0

ニース。私は、コールの間にオプションの「遅延」を追加しました。いくつかの外部コードが解決するイベントを必要とする場合(私はKnockoutを使用します) –

関連する問題