How to use dojo / promise / Promise.cancel () in an Inteceptor template

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; } ) ); 
+4
source share
1 answer

promises are really powerful, I think you should try and understand the two execution paths that are available through the then function (assuming that always is just a shortcut to calling then with the same function as both parameters):

promise.then(successCallback, errorCallback)

  • returns a promise.
  • This promise is permitted (success) if:
  • either successCallback or errorCallback return a value. A promise is either permitted with this value, or if this value is a promise, it is resolved with the resolution of this promise.

  • This promise is rejected (error) if:

  • either successCallback or errorCallback throw an error.

Also, if errorCallback is not provided, if the original promise is rejected (error), it swells to the next level that the error handler provides, so if I do this:

 promise.then(func1).then(func3).then(finalFunc, errorHandler); promise.reject(someError); 

Then errorHandler is called using someError .

All this means that if you don’t want to deal with an error at a certain level, just don’t do it, let it bubble in the chain and implement one error handler at the highest level. If you want to deal with certain errors, you can "wrap it or catch it" as follows:

 promise.then(successFunction, function(error) { if(error.code > 400) { // do something clever, maybe just send an empty result up the chain return []; // goes to successCallbacks! } else { throw error; // pass it to the next errorHandler } }); 

So, to complete and try to answer your questions:

How to pass successful requests back to the original call method?

You can simply return , and the value will be passed to the next successHandler.

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.

Unfortunately, you are not allowed to stop the chain; promises are designed to reliably transition to completion. However, you cannot place the error on each node, add it only when you really need it, and your solution should be pretty clean.

+5
source

All Articles