1. ホーム
  2. jquery

[解決済み] jQuery deferredの "then "メソッドと "pipe "メソッドはいつ使うべきですか?

2023-01-11 02:55:42

質問

jQueryの Deferred には、関数の非同期連結を実装するために使用できる2つの関数があります。

then()

<ブロッククオート

deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred

doneCallbacks Deferredが解決された時に呼び出される関数、または関数の配列です。

failCallbacks Deferredが拒否されたときに呼び出される関数、または関数の配列。

pipe()

<ブロッククオート

deferred.pipe( [doneFilter] [, failFilter] ) Returns: Promise

doneFilter Deferredが解決されたときに呼び出されるオプションの関数です。

failFilter Deferredが拒否されたときに呼び出されるオプションの関数です。

知っている then() よりも少し前から存在しています。 pipe() よりも少し前から存在しているので、後者の方が何か特別な利点があるはずなのですが、その違いが正確には何なのかが私にはわかりません。どちらも名前は違いますが、ほとんど同じコールバック・パラメータを取ります。 Deferred を返すのと Promise はわずかなようです。

私は公式のドキュメントを何度も読みましたが、いつもあまりにも "dense" で、私の頭を本当に包むことができません。検索すると、1 つの機能または他の機能についての多くの議論が見つかりますが、それぞれの異なる利点と欠点を本当に明確にしているものは見つかっていません。

では、どのような場合に then を使うのが良いのか、それとも pipe ?


追加

Felixの素晴らしい回答 のおかげで、この2つの機能がどのように違うのかがとても明確になりました。しかし、私は then() よりも pipe() .

これは、明らかに pipe() よりも強力です。 then() よりも強力で、前者は後者ができることは何でもできるようです。を使用する理由のひとつは then() を使う理由のひとつは、その名前が同じデータを処理する関数の連鎖の終端としての役割を反映しているからかもしれません。

しかし then() が元の Deferred でできないことを pipe() を返すため Promise ?

どのように解決するのですか?

では jQuery 1.8 .then と同じ挙動をします。 .pipe :

非推奨のお知らせです。 jQuery 1.8より、以下のように deferred.pipe() メソッドは非推奨です。このメソッドは deferred.then() メソッドを使用する必要があります。

jQuery 1.8 時点で を追加しました。 deferred.then() メソッドは、関数を通して遅延の状態と値をフィルタリングできる新しいプロミスを返し、今では非推奨となっている deferred.pipe() メソッドに代わるものです。

以下の例は、まだ一部の人にとって役に立つかもしれません。


これらは異なる目的を果たします。

  • .then() は、処理の結果、つまりドキュメントに書かれているように、 遅延されたオブジェクトが解決または拒否されたときに、いつでも使用することができます。これは .done() または .fail() .

  • あなたは .pipe() に、(前) フィルタ を実行し、何らかの形で結果を得ることができます。へのコールバックの返り値は .pipe() への引数として渡されます。 donefail のコールバックがあります。また、別の遅延オブジェクトを返すこともでき、以下のコールバックはこの遅延に登録されます。

    というのは .then() (または .done() , .fail() ) の場合、登録されたコールバックの返り値は単に無視されます。

ですから、あなたが .then() または .pipe() . あなたは かもしれない 使用 .pipe() と同じ目的で .then() と同じ目的で使用できますが、逆は成り立ちません。


例1

ある操作の結果は、オブジェクトの配列です。

[{value: 2}, {value: 4}, {value: 6}]

で、その値の最小値と最大値を計算したいとします。ここでは、2つの done のコールバックを使うとします。

deferred.then(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    var min = Math.min.apply(Math, values);

   /* do something with "min" */

}).then(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    var max = Math.max.apply(Math, values);

   /* do something with "max" */ 

});

どちらの場合も、リストに対して反復処理を行い、各オブジェクトから値を抽出する必要があります。

事前に値を抽出しておけば、両方のコールバックで個別に処理する必要がないのでは?はい!そうです。そして、それは私たちが使用できるものです .pipe() を使用することができます。

deferred.pipe(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    return values; // [2, 4, 6]

}).then(function(result) {
    // result = [2, 4, 6]

    var min = Math.min.apply(Math, result);

    /* do something with "min" */

}).then(function(result) {
    // result = [2, 4, 6]

    var max = Math.max.apply(Math, result);

    /* do something with "max" */

});

明らかにこれはでっち上げの例で、この問題を解決する多くの異なる(たぶんより良い)方法がありますが、ポイントを説明していることを望みます。


例 2

Ajaxの呼び出しについて考えてみましょう。時には、前の呼び出しが完了した後に、1つのAjaxの呼び出しを開始したい場合があります。一つの方法は、2回目の呼び出しを done コールバックの中で2回目の呼び出しを行うことです。

$.ajax(...).done(function() {
    // executed after first Ajax
    $.ajax(...).done(function() {
        // executed after second call
    });
});

さて、コードを分離して、これら2つのAjaxコールを関数内に置きたいと仮定してみましょう。

function makeCalls() {
    // here we return the return value of `$.ajax().done()`, which
    // is the same deferred object as returned by `$.ajax()` alone

    return $.ajax(...).done(function() {
        // executed after first call
        $.ajax(...).done(function() {
            // executed after second call
        });
    });
}

を呼び出す他のコードに、遅延オブジェクトを使用したいと思います。 makeCalls を呼び出す他のコードに 第二 Ajaxの呼び出しですが

makeCalls().done(function() {
    // this is executed after the first Ajax call
});

の中で呼び出されるため、期待される効果は得られません。 done コールバックの内部で行われ、外部からはアクセスできないためです。

解決策としては .pipe() を使うことです。

function makeCalls() {
    // here we return the return value of `$.ajax().pipe()`, which is
    // a new deferred/promise object and connected to the one returned
    // by the callback passed to `pipe`

    return $.ajax(...).pipe(function() {
        // executed after first call
        return $.ajax(...).done(function() {
            // executed after second call
        });
    });
}

makeCalls().done(function() {
    // this is executed after the second Ajax call
});

を使うことで .pipe() を使うことで、呼び出しの実際のフロー/順序を公開することなく、コールバックを "inner" Ajax 呼び出しに追加することができるようになりました。


一般的に、遅延オブジェクトはコードを切り離すための興味深い方法を提供します。)