diff --git a/README.md b/README.md index 8ce16091de..d409c79a5b 100755 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Promise based HTTP client for the browser and node.js - [Custom instance defaults](#custom-instance-defaults) - [Config order of precedence](#config-order-of-precedence) - [Interceptors](#interceptors) + - [Multiple Interceptors](#multiple-interceptors) - [Handling Errors](#handling-errors) - [Cancellation](#cancellation) - [Using application/x-www-form-urlencoded format](#using-applicationx-www-form-urlencoded-format) @@ -645,6 +646,21 @@ axios.interceptors.request.use(function (config) { }, null, { runWhen: onGetCall }); ``` +### Multiple Interceptors + +Given you add multiple response interceptors +and when the response was fulfilled +- then each interceptor is executed +- then they are executed in the order they were added +- then only the last interceptor's result is returned +- then every interceptor receives the result of it's predecessor +- and when the fulfillment-interceptor throws + - then the following fulfillment-interceptor is not called + - then the following rejection-interceptor is called + - once caught, another following fulfill-interceptor is called again (just like in a promise chain). + +Read [the interceptor tests](./test/specs/interceptors.spec.js) for seeing all this in code. + ## Handling Errors ```js diff --git a/test/specs/interceptors.spec.js b/test/specs/interceptors.spec.js index d8768f911e..36b12b761f 100644 --- a/test/specs/interceptors.spec.js +++ b/test/specs/interceptors.spec.js @@ -337,36 +337,143 @@ describe('interceptors', function () { }); }); - it('should add multiple response interceptors', function (done) { - var response; + describe('given you add multiple response interceptors', function () { + + describe('and when the response was fulfilled', function () { + + function fireRequestAndExpect(expectation) { + var response; + axios('/foo').then(function(data) { + response = data; + }); + getAjaxRequest().then(function (request) { + request.respondWith({ + status: 200, + responseText: 'OK' + }); + + setTimeout(function() { + expectation(response) + }, 100); + }); + } + + it('then each interceptor is executed', function (done) { + var interceptor1 = jasmine.createSpy('interceptor1'); + var interceptor2 = jasmine.createSpy('interceptor2'); + axios.interceptors.response.use(interceptor1); + axios.interceptors.response.use(interceptor2); + + fireRequestAndExpect(function () { + expect(interceptor1).toHaveBeenCalled(); + expect(interceptor2).toHaveBeenCalled(); + done(); + }); + }); - axios.interceptors.response.use(function (data) { - data.data = data.data + '1'; - return data; - }); - axios.interceptors.response.use(function (data) { - data.data = data.data + '2'; - return data; - }); - axios.interceptors.response.use(function (data) { - data.data = data.data + '3'; - return data; - }); + it('then they are executed in the order they were added', function (done) { + var interceptor1 = jasmine.createSpy('interceptor1'); + var interceptor2 = jasmine.createSpy('interceptor2'); + axios.interceptors.response.use(interceptor1); + axios.interceptors.response.use(interceptor2); - axios('/foo').then(function (data) { - response = data; - }); + fireRequestAndExpect(function () { + expect(interceptor1).toHaveBeenCalledBefore(interceptor2); + done(); + }); + }); - getAjaxRequest().then(function (request) { - request.respondWith({ - status: 200, - responseText: 'OK' + it('then only the last interceptor\'s result is returned', function (done) { + axios.interceptors.response.use(function() { + return 'response 1'; + }); + axios.interceptors.response.use(function() { + return 'response 2'; + }); + + fireRequestAndExpect(function (response) { + expect(response).toBe('response 2'); + done(); + }); }); - setTimeout(function () { - expect(response.data).toBe('OK123'); - done(); - }, 100); + it('then every interceptor receives the result of it\'s predecessor', function (done) { + axios.interceptors.response.use(function() { + return 'response 1'; + }); + axios.interceptors.response.use(function(response) { + return [response, 'response 2']; + }); + + fireRequestAndExpect(function (response) { + expect(response).toEqual(['response 1', 'response 2']); + done(); + }); + }); + + describe('and when the fulfillment-interceptor throws', function () { + + function fireRequestCatchAndExpect(expectation) { + axios('/foo').catch(function(data) { + // dont handle result + }); + getAjaxRequest().then(function (request) { + request.respondWith({ + status: 200, + responseText: 'OK' + }); + + setTimeout(function() { + expectation() + }, 100); + }); + } + + it('then the following fulfillment-interceptor is not called', function (done) { + axios.interceptors.response.use(function() { + throw Error('throwing interceptor'); + }); + var interceptor2 = jasmine.createSpy('interceptor2'); + axios.interceptors.response.use(interceptor2); + + fireRequestCatchAndExpect(function () { + expect(interceptor2).not.toHaveBeenCalled(); + done(); + }); + }); + + it('then the following rejection-interceptor is called', function (done) { + axios.interceptors.response.use(function() { + throw Error('throwing interceptor'); + }); + var unusedFulfillInterceptor = function() {}; + var rejectIntercept = jasmine.createSpy('rejectIntercept'); + axios.interceptors.response.use(unusedFulfillInterceptor, rejectIntercept); + + fireRequestCatchAndExpect(function () { + expect(rejectIntercept).toHaveBeenCalled(); + done(); + }); + }); + + it('once caught, another following fulfill-interceptor is called again (just like in a promise chain)', function (done) { + axios.interceptors.response.use(function() { + throw Error('throwing interceptor'); + }); + + var unusedFulfillInterceptor = function() {}; + var catchingThrowingInterceptor = function() {}; + axios.interceptors.response.use(unusedFulfillInterceptor, catchingThrowingInterceptor); + + var interceptor3 = jasmine.createSpy('interceptor3'); + axios.interceptors.response.use(interceptor3); + + fireRequestCatchAndExpect(function () { + expect(interceptor3).toHaveBeenCalled(); + done(); + }); + }); + }); }); });