0

基本的に次のような関数があります。

function defTest()
{
    var dfd = new jQuery.Deferred();
    $.ajax(
    {
        type: "GET",
        url: 'http://XXXX',
        cache: false,
        dataType: "json",
        success: function(data,status)
        {
            console.log('ajax done: success');
            dfd.resolve();
        },
        error: function(data,status)
        {
            console.log('ajax done: fail');
            dfd.reject();

        }
    });
    console.log('about to return dfd');
    return dfd;    
}

私はそれをこのように呼びます:

defTest().then(.....);

コンソールログはこれを生成します:dfd code.js:106 ajax doneを返します:success code.js:96

私を混乱させるのは、コードが機能しているように見えることです。それでも、ajaxが終了する前にdfdが返されます。だから私はリターンdfdを削除しました。そして、それを各ajaxハンドラー関数の最後に配置して、Ajaxが終了するまでこれが返されないようにします。

success: function(data,status)
{
    console.log('ajax done: success');
    dfd.resolve();
    return dfd;
}

その後、まったく機能しませんでした。私は混乱しています!誰かが私の延期されたオブジェクトがajaxの成功とエラーハンドラーに含まれない理由と、Ajaxが終了して解決または拒否される前に、延期されたオブジェクトが起動されても返されるように見えるのに、なぜそれが機能するのかを説明できますか?どうしてそれも可能ですか?

編集:この問題は、以前の未回答のより複雑な関数に直接関連しています: 遅延オブジェクトの問題

これが、私の実際の関数には、呼び出し元に返される1つの結果の一部となる他のajax呼び出しが含まれているため、単に「ajax(...)を返す」ことができない理由です。

4

5 に答える 5

1

$.ajaxDeferredオブジェクトを返すので、返す必要があるのはそれだけです。

return $.ajax(...

于 2012-09-12T11:05:21.717 に答える
1

へのdefTest呼び出しは、ajax呼び出しが開始されるとすぐに戻ります。延期が解決されるかどうかまで待機しません。

しかし、あなたはあなたが望むことを完全に行うことができます:

defTest()。then(function(){console.log( "deferred done");})

deferred done延期が最終的に解決されたときに印刷されます。

ちなみに、xdazzが提案しているように、$.ajaxすでにDeferredを返します。

于 2012-09-12T11:07:00.440 に答える
1

このような多くの質問がありますが
AJAXリクエストはasync本質的に存在するため、最初の例では、最後の行でリクエストを返していました。が完了
するのを待つ必要はありません。2番目のケースでは、関数はすでに終了しており、returnを成功させると、イベントに割り当てられたメソッドを直接 呼び出さないため、明らかに何も返されません。UPDATE :-コメントの後、オブジェクトを 返した後、そうしていると、thenハンドラー内の関数は、オブジェクトが解決され たときに明らかに起動されます。 おそらく、オブジェクトを返したらすぐにオブジェクトの値を確認し、使用しないでください。async ajax
success

deffereddefTest().then(.....);
deffered
deffered.then()そして、あなたはここであなたが犯している間違いを得るでしょう
アップデート2-
ここ を見てくださいhttp://jsfiddle.net/BtEKa/im予測可能な結果を​​得る

于 2012-09-12T11:07:15.603 に答える
1

もちろんすぐ返す、そこがポイントです。通常は、遅延オブジェクトの promise メンバーを返しますが、遅延オブジェクトを返し、この関数を呼び出すコードで returnedDeferredObject.promise().then() を使用することもできます。

AJAX の完了に依存する処理がある場合、その処理は返された .promise() の .then() 関数に入ります。すばらしい点は、非同期処理が行われている間、AJAX リターンに依存しない他のことを実行できることです。返された .promise() を他のコードに渡すことができます。

var mydata = somethingThatReturnsPromise(args);

// do a whole bunch of things

mydata.then(function (returnedReponse) {
    // do stuff with returnedResponse that doesn't require DOM ready
});

$(function () {
    mydata.then(function (returnedResponse) {
        // do DOM stuff with returnedPromise
    });
});

私はあなたの要点を見逃していないことを願っていますが、返された約束を、後で何度も使用できるデータソースと考えるのが好きです。指定した .then() コールバックは、returnedResponse がある場合にのみ実行されます.

補足として、私は、jQuery が promise 標準にさらに近づいていることを確信しています。 、progressCb)。

于 2013-03-24T17:59:21.560 に答える
0

あなたの問題は、そのオブジェクトの約束ではなく、遅延オブジェクト全体を返すことだと思います。

プロミス afiak は、非同期呼び出しが返される前に常に返されるため、最後の console.log は PROMISE が返される前にトリガーされますが、ajax が解決されるかなり前に発生します。

.then() の使用も、遅延オブジェクトのステータスに関係なく起動するため、おそらく必要なものではありません: http://api.jquery.com/deferred.then/

おそらく .done() が必要です

これを試して:

function defTest()
{
    var dfd = $.Deferred();
    $.getJSON("http://XXXX").done(function(data,success){
      console.log('ajax done: success');
      dfd.resolve(data);
    }).fail( function(data,status) {
      console.log('ajax done: fail');
      dfd.reject();
    });
    console.log('about to return dfds promise');
    return dfd.promise;    
}
defTest().done(function(data){ console.log(data); });
于 2013-01-17T18:41:51.577 に答える