jQuery jqXHR - 取消链式调用,触发错误链

m0s*_*0sa 14 jquery jquery-1.5 jquery-deferred

我正在创建一个ajax实用程序,用于连接我的服务器方法.我想从jQuery.ajax()调用返回的对象中利用jQuery 1.5+延迟方法.情况如下.

  1. serverside方法始终返回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
    
    Run Code Online (Sandbox Code Playgroud)

所以问题是如何取消所有调用者的调用附加成功回调触发他的错误处理程序在提到的地方????

文档说延迟函数调用列表是FIFO,所以我的成功处理程序绝对是第一个.

rsp*_*rsp 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;
}
Run Code Online (Sandbox Code Playgroud)

现在任何人都可以像对待你的功能一样使用它:

var request = makerequest();

request.done(successCallback);
request.fail(errorCallback);
Run Code Online (Sandbox Code Playgroud)

甚至只是:

makerequest().then(successCallback, errorCallback);
Run Code Online (Sandbox Code Playgroud)

如果你还添加这个:

    promise.success = promise.done;
    promise.error = promise.fail;
Run Code Online (Sandbox Code Playgroud)

那么你的来电将有.success的(也许更熟悉)接口()和.error(),如用纯$阿贾克斯()调用:

var request = makerequest();

request.success(successCallback);
request.error(errorCallback);
Run Code Online (Sandbox Code Playgroud)

(.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;
}
Run Code Online (Sandbox Code Playgroud)

  • **请注意**:这个答案是在2011年2月,那时jQuery是在v1.5.对jQuery的后续改进使得这个答案变得多余.从v1.6开始,普遍接受的解决方案将涉及`deferred.pipe()`和v1.8`deferred.then()`,此时我们会编写类似`function makerequest(){return jqxhr.then (function(data){return(data && data.success)?jqxhr:$ .Deferred().reject(new Error('AJAX data error')).promise();}); }`. (4认同)