首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用失败阻止JQuery承诺从传播到包装

用失败阻止JQuery承诺从传播到包装
EN

Stack Overflow用户
提问于 2018-01-14 20:43:41
回答 1查看 105关注 0票数 1

我的应用程序有很多$.ajax调用,它们大多具有.done.fail函数。

我希望围绕Ajax调用编写一个包装器,这样如果一个函数没有.fail函数,或者如果.fail函数不处理给定的错误(例如,它只处理404,但我得到了一个403),那么我希望包装器可以作为后盾处理它。

以下是我所写的:

代码语言:javascript
复制
function DoAjax(fn, errorText) {
    var deferred = $.Deferred();
    var result = fn();
    if (result === undefined)
        throw 'Function passed into DoAjax has not returned a promise.';
    result.always(function () {
        deferred.resolve(result);
    });
    result.fail(function () {
        alert('fail');
        deferred.fail();
    });
    return deferred.promise();
}

它主要按照我的意愿工作,但失败将执行两次--一次在方法DoAjax中,另一次在Ajax调用的站点上。

我这样执行DoAjax

代码语言:javascript
复制
DoAjax(function () {
        var ajaxCall = $.ajax({
            method: "GET",
            url: baseUrl + "api/test"
        });

        ajaxCall.fail(function() { alert('failed the call'); });

        return ajaxCall;
});

我相信我可能可以通过手动创建一个$.deferred,然后围绕它执行$.ajax调用来实现这一点,但是不希望在它周围有另一个包装器。

我使用的是jQuery 2.2。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-14 23:41:28

是时候好好学习了。有几件事需要考虑进去:

  1. .done().fail()只是没有.then(successCallback, errorCallback) (或jQuery 3+中的.then()/.catch() )所谓的“过滤能力”的jQuery.ajax()选项。换句话说,无论从.done().fail()回调中返回什么,都不会对jqxhr承诺链产生下游影响。
  2. 在jQuery <3时,errorCallback不会自动捕获错误。默认行为是保持在承诺链的错误路径上。为了给一个errorCallback 'catch‘行为,那么你必须从它返回一个坚定的承诺。在jQuery 3+,默认情况下errorCallback捕获,但您可以返回拒绝的承诺或抛出来传播错误条件。
  3. 在本例中,您的fn()返回jqxhr,而不是结果。因此,正如所写的那样,if(result === undefined)测试将始终返回false。jqxhr最终交付的结果不能以这种方式进行测试。
  4. 如果不确定函数是返回值还是承诺,那么将返回的值/对象包装在jQuery.when(...)中,例如$.when(fn())
  5. 有了(3)处理,您可以直接从jQuery.when(...)返回的承诺中链接。不需要显式的$.Deferred()

试试这个:

代码语言:javascript
复制
var baseUrl = '/';
function DoAjax(fn) {
    return $.when(fn()) // no need to test for fn() not returning a promise. `$.when(fn())` forces any non-Promise to Promise.
    .then(function(response) {
        console.log('success!', response);
    }).then(null, function(err) {
        console.error('B', err); // (LOG_2)
    });
}

DoAjax(function () {
    return $.ajax({
        method: "GET",
        url: baseUrl + "api/test"
    }).then(null, function(jqxhr, textStatus) {
        var err = new Error('Whoops! ' + jqxhr.status + ': ' + textStatus);
        console.error('A', err);

        // "throw behaviour"
        return err; // propagate the error (jQuery <3) or `throw err;` (jQuery 3+)

        // "catch behaviour"
        // return $.when('default response'); // "2" mutate failure into success (jQuery <3) or `return 'default response';` (jQuery 3+)
    });
});

小提琴

现在,尝试交换标记为“繁殖行为”和“捕获行为”的行,并观察日志中的差异。

如果你不马上拿到的话就别担心。学习这些东西需要时间。

如果您有选择,那么使用jQuery 3+,其中jqxhr和其他承诺更接近javascript的原生Promise,而不是jQuery <3。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48253972

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档