如何在Promise中使用默认拒绝处理程序

时间:2019-03-19 07:40:03

标签: javascript

我会无条件地发出Ajax请求,并且通常以相同的方式处理错误。所以例如如果发生404,则默认情况下,我只会显示标准错误消息。但是在某些情况下,我还想做其他事情。

注意:我正在使用ExtJS 4来执行实际的Ajax请求,但这不是特定于ExtJS的问题。 ExtJS不使用Promises,因此我基本上是将其API转换为Promise API。

这是代码:

var defaultErrorHandler = function(response) {
    // do some default stuff like displaying an error message
};

var ajaxRequest = function(config) {
    return new Promise(function(fulfill, reject) {
        var ajaxCfg = Ext.apply({}, {
            success: function(response) {
                var data = Ext.decode(response.responseText);
                if (data.success) {
                    fulfill(data);
                } else {
                    defaultErrorHandler(response);
                    reject(response);
                }
            },
            failure: function(response) {
                defaultErrorHandler(response);
                reject(response);
            }
        }, config);
        Ext.Ajax.request(ajaxCfg);
    });
};

// usage without special error handling:
ajaxRequest({url: '/some/request.json'}).then(function(data) {
    // do something
});

// usage with special error handling:
ajaxRequest({url: '/some/request.json'}).then(function(data) {
    // do something
}, function(response) {
    // do some additional error handling
});

现在的问题:“没有特殊错误处理的用法”不起作用,因为如果我不提供拒绝功能,它将引发错误。为了解决这个问题,我被迫提供一个空函数,如下所示:

// usage without special error handling:
ajaxRequest({url: '/some/request.json'}).then(function(data) {
    // do something
}, function() {});

每次都提供一个空函数(在我的代码库中,这将是数百次)很丑陋,所以我希望有一个更优雅的解决方案。

我也不想使用catch(),因为那样会捕获所有抛出的错误,即使它发生在fulfill函数中。但是我的代码中发生的实际错误不应该处理,应该出现在控制台中。

1 个答案:

答案 0 :(得分:0)

除非您希望提供一个未处理的拒绝处理程序,否则没有“所有承诺的默认错误处理程序”这样的东西。但是,这不仅限于您对ajax请求的承诺。

最简单,最好的解决方案是仅公开您的defaultErrorHandler,并让每个调用者根据您的诺言明确向其传递then调用。如果他们不想使用它,他们要么需要提供自己的特殊错误处理程序,要么会被拒绝。该解决方案提供了最大的灵活性,例如允许进一步处理拒绝。

如果这不是您想要的,而是需要立即处理ajax错误,那么最好的选择是覆盖所返回的promise的then方法:

function defaultingThen(onfulfill, onreject = defaultErrorHandler) {
    return Promise.prototype.then.call(this, onfulfill, onreject);
}
function ajaxRequest(config) {
    return Object.assign(new Promise(function(resolve, reject) {
        Ext.Ajax.request({
            ...config,
            success: function(response) {
                var data = Ext.decode(response.responseText);
                if (data.success) {
                    resolve(data);
                } else {
                    reject(response);
                }
            },
            failure: reject,
        });
    }), {
        then: defaultingThen,
    });
}