I want to implement an Inteceptor pattern for a specific AJAX controller.
Any AJAX request in my application will call Authenticator.request (), which will intercept the response, check certain statuses (for example, 401, 403, 503), perform the function of displaying a specific application based on them (i.e. display LoginDialog if status 401 ) My problems are related to the confusion around dojo Promises.
- How to pass successful requests back to the original call method?
- When I call dojo.promise.Promise.cancel (), I expect the chain to stop. However, this just launches the errback function. This means that logic must be placed in each errback method in the calling function in order to distinguish between a canceled request and an error.
Can someone explain to me how to use Promises in this situation?
Thanks in advance!
Here is an example of what I thought I could do ...
require(["dojo/request"], function(request){ auth = { request: function() { var promise = request(arguments); return promise.always(function (response) { console.log("always called", response); switch (response.response.status) { case 404: console.log(404, response); return "cancelled"; break; } }); } }; }); auth.request('example.json').then(function(text){ console.log('success!', text) }, function(error){ console.log('error!', error); });
In case this helps someone in the future, here is what I ended up doing (based on Dave's answer) ...
require(["dojo/request", "dojo/errors/CancelError"], function(dRequest, CancelError){ auth = { request: function(url, options) { var promise = dRequest(url, options); return promise.response.then( function (response) { return response; }, function (error) { var error, cancelError = new CancelError(error.message); cancelError.response = error.response; console.log("error", error, cancelError); switch (error.response.status) { case 404: console.log(404, "canceled"); throw cancelError; } throw error; } ); }, cancelTrap: function (errorBack, cancelBack) { return function (error) { throw (error instanceof CancelError) ? cancelBack && cancelBack(error) || error : errorBack && errorBack(error) || error; } } }; });
... it can then be used like that ...
r = auth.request('something.json'); r.then( function(text){ console.log('success! > this', this) console.log('success!', text) return text; }, auth.cancelTrap( function (error) { console.log('error!', error); throw error; }, function (cancelError) { console.log('cancelError!', cancelError); throw cancelError; } ) ).then( function(text){ console.log('success2!', text) }, auth.cancelTrap( function (error) { console.log('error2!', error); throw error; }, function (cancelError) { console.log('cancelError2!', cancelError); throw cancelError; } ) );