web-dev-qa-db-ja.com

jQueryの延期と約束 - .then()と.done()

私はjQueryの延期と約束について読んできましたが、コールバックを成功させるために.then().done()を使うことの違いはわかりません。 Eric Hynds.done().success()が同じ機能に対応していると述べていますが、.then()もそうであると思いますが、これはすべてのコールバックが成功した操作の完了時に呼び出されるからです。

誰かが私に正しい使い方を教えてください。

442
screenm0nkey

done()にアタッチされたコールバックは、延期が解決されたときに起動されます。 fail()にアタッチされたコールバックは、遅延オブジェクトが拒否されたときに発生します。

JQuery 1.8より前は、then()は単なる構文糖衣でした。

promise.then( doneCallback, failCallback )
// was equivalent to
promise.done( doneCallback ).fail( failCallback )

1.8の時点で、then()pipe()の別名であり、新しい約束を返します。pipe()の詳細については here を参照してください。

success()error()は、ajax()の呼び出しによって返されるjqXHRオブジェクトでのみ利用可能です。それぞれdone()fail()の単純なエイリアスです。

jqXHR.done === jqXHR.success
jqXHR.fail === jqXHR.error

また、done()は単一のコールバックに限定されず、非関数を除外します(ただし、バージョン1.8の文字列にはバグがありますが、これは1.8.1で修正されるべきです)。

// this will add fn1 to 7 to the deferred's internal callback list
// (true, 56 and "omg" will be ignored)
promise.done( fn1, fn2, true, [ fn3, [ fn4, 56, fn5 ], "omg", fn6 ], fn7 );

fail()についても同じことが言えます。

550
Julian Aubourg

返される結果が処理される方法にも違いがあります(呼ばれる連鎖、doneは連鎖せず、thenは呼び出し連鎖を生成します)。

promise.then(function (x) { // Suppose promise returns "abc"
    console.log(x);
    return 123;
}).then(function (x){
    console.log(x);
}).then(function (x){
    console.log(x)
})

次の結果がログに記録されます。

abc
123
undefined

しながら

promise.done(function (x) { // Suppose promise returns "abc"
    console.log(x);
    return 123;
}).done(function (x){
    console.log(x);
}).done(function (x){
    console.log(x)
})

次のようになります。

abc
abc
abc

----------更新:

ところで。アトミックタイプの値ではなくPromiseを返した場合、外側の約束は内側の約束が解決するまで待機します。

promise.then(function (x) { // Suppose promise returns "abc"
    console.log(x);
    return $http.get('/some/data').then(function (result) {
        console.log(result); // suppose result === "xyz"
        return result;
    });
}).then(function (result){
    console.log(result); // result === xyz
}).then(function (und){
    console.log(und) // und === undefined, because of absence of return statement in above then
})

このようにして、次のような並列または順次非同期操作を構成することが非常に簡単になります。

// Parallel http requests
promise.then(function (x) { // Suppose promise returns "abc"
    console.log(x);

    var promise1 = $http.get('/some/data?value=xyz').then(function (result) {
        console.log(result); // suppose result === "xyz"
        return result;
    });

    var promise2 = $http.get('/some/data?value=uvm').then(function (result) {
        console.log(result); // suppose result === "uvm"
        return result;
    });

    return promise1.then(function (result1) {
        return promise2.then(function (result2) {
           return { result1: result1, result2: result2; }
        });
    });
}).then(function (result){
    console.log(result); // result === { result1: 'xyz', result2: 'uvm' }
}).then(function (und){
    console.log(und) // und === undefined, because of absence of return statement in above then
})

上記のコードは2つのhttpリクエストを並行して発行するため、リクエストがより早く完了します。一方、これらのhttpリクエストの下では順次実行されるため、サーバの負荷が軽減されます。

// Sequential http requests
promise.then(function (x) { // Suppose promise returns "abc"
    console.log(x);

    return $http.get('/some/data?value=xyz').then(function (result1) {
        console.log(result1); // suppose result1 === "xyz"
        return $http.get('/some/data?value=uvm').then(function (result2) {
            console.log(result2); // suppose result2 === "uvm"
            return { result1: result1, result2: result2; };
        });
    });
}).then(function (result){
    console.log(result); // result === { result1: 'xyz', result2: 'uvm' }
}).then(function (und){
    console.log(und) // und === undefined, because of absence of return statement in above then
})
391
Lu4

.done()にはコールバックが1つだけあり、それが成功コールバックです。

.then()は成功と失敗の両方のコールバックを持ちます

.fail()には失敗コールバックが1つだけあります

それであなたがしなければならないことはあなた次第です。

51
Marino Šimić

deferred.done()

deferredが解決された場合にのみと呼ばれるハンドラを追加します。複数のコールバックを呼び出して呼び出すことができます。

var url = 'http://jsonplaceholder.typicode.com/posts/1';
$.ajax(url).done(doneCallback);

function doneCallback(result) {
    console.log('Result 1 ' + result);
}

このように書くこともできます

function ajaxCall() {
    var url = 'http://jsonplaceholder.typicode.com/posts/1';
    return $.ajax(url);
}

$.when(ajaxCall()).then(doneCallback, failCallback);

deferred.then()

deferredが解決された、拒否された、またはまだ進行中の場合にと呼ばれるハンドラを追加します

var url = 'http://jsonplaceholder.typicode.com/posts/1';
$.ajax(url).then(doneCallback, failCallback);

function doneCallback(result) {
    console.log('Result ' + result);
}

function failCallback(result) {
    console.log('Result ' + result);
}
13
Nipuna

JQueryのDeferredがPromiseの実装であるという意味で(そしてjQuery3.0が実際にそれらを仕様にしようとしている限り)、実際にはかなり重要な違いがあります。

Done/thenの主な違いは、

  • .done()は、あなたが何をしても何を返しても、常に同じPromise/wrapped値を最初に返します。
  • .then()は常に新しいPromiseを返し、あなたはそのPromiseがあなたが渡した関数が何を返したかに基づいて何を制御するかを担当します。

JQueryからネイティブのES2015 Promiseに翻訳された.done()は、Promiseチェーン内の関数の周りに "tap"構造を実装するのと同じようなものです。 ..しかし、その関数の結果はチェーン自体には影響しません。

const doneWrap = fn => x => { fn(x); return x };

Promise.resolve(5)
       .then(doneWrap( x => x + 1))
       .then(doneWrap(console.log.bind(console)));

$.Deferred().resolve(5)
            .done(x => x + 1)
            .done(console.log.bind(console));

それらは両方とも5ではなく6を記録します。

ロギングを行うためにdoneとdoneWrapを使用しました。これはconsole.log関数が実際には何も返さないためです。そして、何も返さない関数を渡すとどうなりますか?

Promise.resolve(5)
       .then(doneWrap( x => x + 1))
       .then(console.log.bind(console))
       .then(console.log.bind(console));

それは記録します:

5

undefined

何が起こった? .thenを使用して何も返さない関数を渡したとき、暗黙の結果は "undefined"でした...もちろん、次のthenメソッドにPromise [undefined]を返しました。だから私たちが始めた当初の価値は基本的に失われました。

.then()は、基本的には関数合成の形式です。各ステップの結果は、次のステップで関数の引数として使用されます。それが.doneが "タップ"として最もよく考えられている理由です - >それは実際には構成の一部ではなく、特定のステップで値を調べてその値で関数を実行するだけのものです。どのように構成しても。

これは非常に根本的な違いです。ネイティブのPromiseが.doneメソッドを自分で実装していないのには、おそらくもっともな理由があります。 .failメソッドが存在しない理由を理解する必要はありません。さらに複雑なものです(つまり、.fail/.catchは.done/.thenのミラーではありません)。 「滞在」は渡されたもののように拒絶されました、彼らは解決します!)

8
Dtipson

then()は常にどんな場合でも呼び出されることを意味します。しかし、渡すパラメーターはjQueryのバージョンによって異なります。

JQuery 1.8より前では、then()done().fail()と同じです。そしてすべてのコールバック関数は同じパラメータを共有します。

しかしjQuery 1.8の時点で、then()は新しい約束を返し、もしそれが値を返すなら、それは次のコールバック関数に渡されるでしょう。

次の例を見てみましょう。

var defer = jQuery.Deferred();

defer.done(function(a, b){
            return a + b;
}).done(function( result ) {
            console.log("result = " + result);
}).then(function( a, b ) {
            return a + b;
}).done(function( result ) {
            console.log("result = " + result);
}).then(function( a, b ) {
            return a + b;
}).done(function( result ) {
            console.log("result = " + result);
});

defer.resolve( 3, 4 );

JQuery 1.8より前では、答えは

result = 3
result = 3
result = 3

すべてのresultは3を取ります。そしてthen()関数は常に同じ遅延オブジェクトを次の関数に渡します。

しかし、jQuery 1.8以降、結果は以下のようになります。

result = 3
result = 7
result = NaN

最初のthen()関数は新しい約束を返し、値7(そしてこれが渡される唯一のパラメータ)が次のdone()に渡されるので、2番目のdone()result = 7を書きます。 2番目のthen()aの値として7を取り、undefinedの値としてbを取ります。したがって、2番目のthen()はパラメーターNaNを使用して新しいpromiseを返し、最後のdone()はその結果としてNaNを出力します。

5
JasmineOT

他の答えで見つけるのは少し難しかった、非常に単純なメンタルマッピングがあります。

1
B M