Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An attempt to explore how error handling in ExtJS AJAX requests work. Use ExtJS, Jasmine
/**
* 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
You can’t perform that action at this time.