Created
September 16, 2019 13:17
-
-
Save twasink/7597f9fbe0cb49564ae9db51111209a8 to your computer and use it in GitHub Desktop.
An attempt to explore how error handling in ExtJS AJAX requests work. Use ExtJS, Jasmine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* An attempt to explore how error handling in ExtJS AJAX requests work, | |
* in particular looking at ways to re-try requests and cope with | |
* both the conventional 'success/fail/callback' style and this | |
* new-fangled 'then/always/otherwise' promise approach. | |
*/ | |
describe("Twasink.spike.AjaxErrorHandlingSpikeSpec", function() { | |
var successHandler; | |
var failHandler; | |
var alwaysHandler; | |
beforeEach(function() { | |
successHandler = jasmine.createSpy("success"); | |
failHandler = jasmine.createSpy("fail"); | |
alwaysHandler = jasmine.createSpy("always"); | |
}) | |
beforeEach(function() { | |
jasmine.Ajax.install(); | |
}); | |
afterEach(function() { | |
jasmine.Ajax.uninstall(); | |
}); | |
beforeAll(function() { | |
Ext.Ajax.on('requestexception', 'listener', ajaxErrorHandler); | |
}) | |
beforeEach(function() { | |
ajaxErrorHandler.called = false; | |
}) | |
afterEach(function() { | |
ajaxErrorHandler.originalOptions = null; | |
ajaxErrorHandler.originalDeferred = null; | |
}) | |
// Each approach for making an AJAX call differs in calling style, but should all be | |
// treated the same. To facilitate this, I'm using a little meta-programming here, | |
// defining a test suit as an object that I can call into multiple times, | |
// each time with a new ajax handler. | |
function runAjaxTests(title, ajaxCall) { | |
describe(title, function() { | |
function makeAjaxCall() { | |
ajaxCall(); | |
expect(jasmine.Ajax.requests.mostRecent().url).toBe('http://example.org/'); | |
} | |
// Prove I know how to make a normal call that works. | |
it("successful call example", function(done) { | |
makeAjaxCall(); | |
jasmine.Ajax.requests.mostRecent().respondWith({ | |
status: 200 | |
}); | |
Ext.asap(function() { | |
expect(ajaxErrorHandler.called).not.toBeTruthy(); | |
expect(successHandler.calls.count()).toEqual(1); | |
expect(failHandler.calls.count()).toEqual(0); | |
expect(alwaysHandler.calls.count()).toEqual(1); | |
done() | |
}) | |
}) | |
// Prove I know how to make a normal call that fails. | |
it("unhandled error example", function(done) { | |
makeAjaxCall(); | |
jasmine.Ajax.requests.mostRecent().respondWith({ | |
status: 500 | |
}); | |
Ext.asap(function() { | |
expect(ajaxErrorHandler.called).toBeTruthy(); | |
expect(successHandler.calls.count()).toEqual(0); | |
expect(failHandler.calls.count()).toEqual(1); | |
expect(alwaysHandler.calls.count()).toEqual(1); | |
done(); | |
}) | |
}) | |
// Prove I know how to make a normal call that fails and is retried. | |
it("handled error", function(done) { | |
makeAjaxCall(); | |
expect(ajaxErrorHandler.called).not.toBeTruthy(); | |
expect(jasmine.Ajax.requests.count()).toEqual(1); | |
jasmine.Ajax.requests.mostRecent().respondWith({ | |
status: 401 | |
}); | |
expect(ajaxErrorHandler.called).toBeTruthy(); | |
// Nothing should have been called. | |
expect(successHandler.calls.count()).toEqual(0); | |
expect(failHandler.calls.count()).toEqual(0); | |
expect(alwaysHandler.calls.count()).toEqual(0); | |
ajaxErrorHandler.retryCall(); | |
expect(jasmine.Ajax.requests.count()).toEqual(2); | |
jasmine.Ajax.requests.mostRecent().respondWith({ | |
status: 200 | |
}); | |
Ext.asap(function() { | |
expect(successHandler.calls.count()).toEqual(1); | |
expect(failHandler.calls.count()).toEqual(0); | |
expect(alwaysHandler.calls.count()).toEqual(1); | |
done(); | |
}) | |
}) | |
}) | |
} | |
// And here's our attempt at handling the error. All we'll do here is make a new Ajax call and do our | |
// best to cancel the old one. | |
var ajaxErrorHandler = { | |
listener: function(connection, response, options) { | |
this.called = true; | |
// Start by doing nothing, and seeing the red bar | |
var originalRequest = response.request; | |
switch(response.status) { | |
case 401: | |
this.handleTheError(originalRequest, response, options); | |
return; | |
default: | |
// do nothing by default | |
return | |
} | |
}, | |
handleTheError: function(request, response, options) { | |
console.log("Handling 401 error"); | |
// capture the details. | |
this.originalOptions = Ext.clone(options); | |
this.originalDeferred = request.deferred; | |
// stop the original error. | |
options.failure = null; | |
// stop the callback, if any | |
options.callback = null; | |
request.deferred = null; | |
}, | |
retryCall: function() { | |
var request = Ext.Ajax.request(this.originalOptions); | |
request.deferred = this.originalDeferred; | |
} | |
} | |
runAjaxTests("Conventional Ajax Approach", function() { | |
Ext.Ajax.request({ | |
url: 'http://example.org/', | |
disableCaching: false, | |
success: successHandler, | |
failure: failHandler, | |
callback: alwaysHandler | |
}) | |
}); | |
runAjaxTests("Promise-style Approach 1", function() { | |
Ext.Ajax.request({ | |
url: 'http://example.org/', | |
disableCaching: false, | |
}) | |
.then(successHandler, failHandler) | |
.always(alwaysHandler) | |
}) | |
runAjaxTests("Promise-style Approach 2", function() { | |
Ext.Ajax.request({ | |
url: 'http://example.org/', | |
disableCaching: false, | |
}) | |
.then(successHandler) | |
.otherwise(failHandler) | |
.always(alwaysHandler) | |
}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment