0

I make Ajax requests with a Promise and usually handle errors the same way. So e.g. if a 404 happens, then I would just display a standard error message by default. But in some cases I want to do something else.

Note: I'm using ExtJS 4 to do the actual Ajax request, but this issue is not specific to ExtJS. ExtJS does not use Promises, so I'm basically converting their API to a Promise API.

This is the code:

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
});

Now the problem: The "usage without special error handling" does not work, because if I do not provide a reject function, it will throw an error. To fix this, I am forced to provide an empty function, like so:

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

Having to provide an empty function every time (and in my code base this will be hundreds of times) is ugly, so I was hoping there was a more elegant solution.

I also do not want to use catch() since that would catch ALL errors thrown, even if it happens in the fulfill function. But actual errors happening in my code should not be handled, they should appear in the console.

entreprenr
  • 346
  • 2
  • 13
  • 1
    You can write a special error handling function which will do nothing on if error is not special and then pass that function to reject block. In that way you don't have to pass empty function every time but need to pass special error handling function every time. – Rahul Raut Mar 19 '19 at 07:56

1 Answers1

0

There is no such thing a "default error handler for all promises", unless you are looking to provide an unhandled rejection handler. That would however not be restricted to the promises for your ajax requests.

The simplest and best solution would be to just expose your defaultErrorHandler and have every caller explicitly pass it the then invocation on your promise. If they don't want to use it, they either need to provide their own special error handler or they will get a rejected promise. This solution provides maximum flexibility, such as allowing to handle the rejection further down the chain.

If that is not what you want to do, but instead require immediate handling of the ajax error, your best bet is to override the then method of your returned promises:

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,
    });
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375