15

我正在创建一个用于与我的服务器方法交互的 ajax 实用程序。我想利用 jQuery.ajax() 调用返回的对象中的 jQuery 1.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

更新:请注意,当前 jQuery Promises 与Promises/A+ 规范 不兼容-此答案中的更多信息。)

在您创建 AJAX 请求的函数中,您还可以创建一个延迟对象,并在将其解析和拒绝函数绑定到具有一些自定义数据验证的 $.ajax 请求的适当回调后,向调用者返回一个承诺,如下所示:

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;

那么你的调用者将拥有(可能更熟悉) .success() 和 .error() 接口,就像纯 $.ajax() 调用一样:

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 回答