15

サーバーメソッドとインターフェイスするためのajaxユーティリティを作成しています。jQuery.ajax()呼び出しから返されたオブジェクトからjQuery1.5以降の遅延メソッドを利用したいと思います。状況は以下の通りです。

  1. サーバーサイドメソッドは常にJSONオブジェクトを返します。

    { success: true|false, data: ... }

  2. クライアント側のユーティリティは、次のようにajax呼び出しを開始します

    var jqxhr = $.ajax({ ... });

  3. そして問題領域:

    jqxhr.success(function(data, textStatus, xhr) {
         if(!data || !data.success) { 
             ???? // abort processing, trigger error
         }
    });
    return jqxhr; // return to caller so he can attach his own handlers
    

したがって、問題は、成功コールバックが追加されたすべての呼び出し元の呼び出しをキャンセルして、?????で示された場所でエラーハンドラーをトリガーする方法です。

ドキュメントには、遅延関数呼び出しリストはFIFOであると記載されているため、私の成功ハンドラーは間違いなく最初のものです。

4

1 に答える 1

29

更新:現在、jQueryPromisesはPromises/ A +仕様 と互換性がないことに注意してください-この回答の詳細を参照してください。)

AJAXリクエストを作成する関数では、次のようなカスタムデータ検証を使用して、resolve関数とreject関数を$ .ajaxリクエストの適切なコールバックにバインドした後、遅延オブジェクトを作成して呼び出し元にpromiseを返すこともできます。

function makerequest() {

    var deferred = $.Deferred();
    var promise = deferred.promise();

    var jqxhr = $.ajax({
        // ...
    });

    jqxhr.success(function(data, status, xhr) {
        if (!data || !data.success) {
            deferred.reject(jqxhr, 'error');
        } else {
            deferred.resolve(data, status, xhr);
        }
    });

    jqxhr.error(function(jqXHR, status, error) {
        deferred.reject(jqXHR, status, error);
    });

    return promise;
}

これで、誰もがあなたの関数に対してこのような約束のようにそれを使用できるようになります。

var request = makerequest();

request.done(successCallback);
request.fail(errorCallback);

または単に:

makerequest().then(successCallback, errorCallback);

これも追加する場合:

    promise.success = promise.done;
    promise.error = promise.fail;

そうすれば、呼び出し元は、純粋な$ .ajax()呼び出しのように、.success()および.error()の(おそらくより馴染みのある)インターフェースを持つことになります。

var request = makerequest();

request.success(successCallback);
request.error(errorCallback);

(.complete()の実装は、読者の演習として残されています。)

このデモをご覧ください:

作業中のプロジェクトから直接引き出された別の例を次に示します。

function ajax(url, data) {
    var self = this;
    var deferred = $.Deferred();
    var promise = deferred.promise();

    var jqxhr = $.ajax({
        url: url,
        data: JSON.stringify(data),
        contentType: "application/json; charset=utf-8",
        dataType: 'json',
        type: 'POST'
    }).done(function (msg, status, xhr) {
        if (!msg || msg.Error) {
            self.doError(msg.Error);
            deferred.reject(jqxhr, 'error');
        } else {
            deferred.resolve(msg, status, xhr);
        }
    });

    return promise;
}
于 2011-02-25T01:45:26.970 に答える