mirror of
https://github.com/tenrok/axios.git
synced 2026-06-20 20:00:40 +03:00
Adding cancellation support
This commit is contained in:
@@ -185,6 +185,15 @@ module.exports = function httpAdapter(config) {
|
|||||||
}, config.timeout);
|
}, config.timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.cancelToken) {
|
||||||
|
// Handle cancellation
|
||||||
|
config.cancelToken.promise.then(function onCanceled(cancel) {
|
||||||
|
req.abort();
|
||||||
|
reject(cancel);
|
||||||
|
aborted = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Send the request
|
// Send the request
|
||||||
if (utils.isStream(data)) {
|
if (utils.isStream(data)) {
|
||||||
data.pipe(req);
|
data.pipe(req);
|
||||||
|
|||||||
@@ -153,6 +153,15 @@ module.exports = function xhrAdapter(config) {
|
|||||||
request.upload.addEventListener('progress', config.onUploadProgress);
|
request.upload.addEventListener('progress', config.onUploadProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.cancelToken) {
|
||||||
|
// Handle cancellation
|
||||||
|
config.cancelToken.promise.then(function onCanceled(cancel) {
|
||||||
|
request.abort();
|
||||||
|
reject(cancel);
|
||||||
|
// Clean up request
|
||||||
|
request = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (requestData === undefined) {
|
if (requestData === undefined) {
|
||||||
requestData = null;
|
requestData = null;
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ axios.create = function create(defaultConfig) {
|
|||||||
return createInstance(defaultConfig);
|
return createInstance(defaultConfig);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Expose Cancel & CancelToken
|
||||||
|
axios.Cancel = require('./cancel/Cancel');
|
||||||
|
axios.CancelToken = require('./cancel/CancelToken');
|
||||||
|
|
||||||
// Expose all/spread
|
// Expose all/spread
|
||||||
axios.all = function all(promises) {
|
axios.all = function all(promises) {
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
|
|||||||
@@ -2,6 +2,16 @@
|
|||||||
|
|
||||||
var utils = require('./../utils');
|
var utils = require('./../utils');
|
||||||
var transformData = require('./transformData');
|
var transformData = require('./transformData');
|
||||||
|
var Cancel = require('../cancel/Cancel');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws a `Cancel` if cancellation has been requested.
|
||||||
|
*/
|
||||||
|
function throwIfCancellationRequested(config) {
|
||||||
|
if (config.cancelToken) {
|
||||||
|
config.cancelToken.throwIfRequested();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatch a request to the server using whichever adapter
|
* Dispatch a request to the server using whichever adapter
|
||||||
@@ -11,6 +21,8 @@ var transformData = require('./transformData');
|
|||||||
* @returns {Promise} The Promise to be fulfilled
|
* @returns {Promise} The Promise to be fulfilled
|
||||||
*/
|
*/
|
||||||
module.exports = function dispatchRequest(config) {
|
module.exports = function dispatchRequest(config) {
|
||||||
|
throwIfCancellationRequested(config);
|
||||||
|
|
||||||
// Ensure headers exist
|
// Ensure headers exist
|
||||||
config.headers = config.headers || {};
|
config.headers = config.headers || {};
|
||||||
|
|
||||||
@@ -52,6 +64,8 @@ module.exports = function dispatchRequest(config) {
|
|||||||
// Wrap synchronous adapter errors and pass configuration
|
// Wrap synchronous adapter errors and pass configuration
|
||||||
.then(adapter)
|
.then(adapter)
|
||||||
.then(function onFulfilled(response) {
|
.then(function onFulfilled(response) {
|
||||||
|
throwIfCancellationRequested(config);
|
||||||
|
|
||||||
// Transform response data
|
// Transform response data
|
||||||
response.data = transformData(
|
response.data = transformData(
|
||||||
response.data,
|
response.data,
|
||||||
@@ -60,16 +74,20 @@ module.exports = function dispatchRequest(config) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}, function onRejected(error) {
|
}, function onRejected(reason) {
|
||||||
// Transform response data
|
if (!(reason instanceof Cancel)) {
|
||||||
if (error && error.response) {
|
throwIfCancellationRequested(config);
|
||||||
error.response.data = transformData(
|
|
||||||
error.response.data,
|
// Transform response data
|
||||||
error.response.headers,
|
if (reason && reason.response) {
|
||||||
config.transformResponse
|
reason.response.data = transformData(
|
||||||
);
|
reason.response.data,
|
||||||
|
reason.response.headers,
|
||||||
|
config.transformResponse
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(error);
|
return Promise.reject(reason);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
var Cancel = axios.Cancel;
|
||||||
|
var CancelToken = axios.CancelToken;
|
||||||
|
|
||||||
|
describe('cancel', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
jasmine.Ajax.install();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
jasmine.Ajax.uninstall();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when called before sending request', function() {
|
||||||
|
it('rejects Promise with a Cancel object', function (done) {
|
||||||
|
var source = CancelToken.source();
|
||||||
|
source.cancel('Operation has been canceled.');
|
||||||
|
axios.get('/foo', {
|
||||||
|
cancelToken: source.token
|
||||||
|
}).catch(function (thrown) {
|
||||||
|
expect(thrown).toEqual(jasmine.any(Cancel));
|
||||||
|
expect(thrown.message).toBe('Operation has been canceled.');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when called after request has been sent', function() {
|
||||||
|
it('rejects Promise with a Cancel object', function (done) {
|
||||||
|
var source = CancelToken.source();
|
||||||
|
axios.get('/foo/bar', {
|
||||||
|
cancelToken: source.token
|
||||||
|
}).catch(function (thrown) {
|
||||||
|
expect(thrown).toEqual(jasmine.any(Cancel));
|
||||||
|
expect(thrown.message).toBe('Operation has been canceled.');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
getAjaxRequest().then(function (request) {
|
||||||
|
// call cancel() when the request has been sent, but a response has not been received
|
||||||
|
source.cancel('Operation has been canceled.');
|
||||||
|
request.respondWith({
|
||||||
|
status: 200,
|
||||||
|
responseText: 'OK'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls abort on request object', function (done) {
|
||||||
|
var source = CancelToken.source();
|
||||||
|
var request;
|
||||||
|
axios.get('/foo/bar', {
|
||||||
|
cancelToken: source.token
|
||||||
|
}).catch(function() {
|
||||||
|
// jasmine-ajax sets statusText to 'abort' when request.abort() is called
|
||||||
|
expect(request.statusText).toBe('abort');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
getAjaxRequest().then(function (req) {
|
||||||
|
// call cancel() when the request has been sent, but a response has not been received
|
||||||
|
source.cancel();
|
||||||
|
request = req;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -11,7 +11,14 @@ describe('instance', function () {
|
|||||||
var instance = axios.create();
|
var instance = axios.create();
|
||||||
|
|
||||||
for (var prop in axios) {
|
for (var prop in axios) {
|
||||||
if (['Axios', 'create', 'all', 'spread', 'default'].indexOf(prop) > -1) {
|
if ([
|
||||||
|
'Axios',
|
||||||
|
'create',
|
||||||
|
'Cancel',
|
||||||
|
'CancelToken',
|
||||||
|
'all',
|
||||||
|
'spread',
|
||||||
|
'default'].indexOf(prop) > -1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
expect(typeof instance[prop]).toBe(typeof axios[prop]);
|
expect(typeof instance[prop]).toBe(typeof axios[prop]);
|
||||||
|
|||||||
@@ -320,5 +320,21 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
testCancel: function(test) {
|
||||||
|
var source = axios.CancelToken.source();
|
||||||
|
server = http.createServer(function (req, res) {
|
||||||
|
// call cancel() when the request has been sent, but a response has not been received
|
||||||
|
source.cancel('Operation has been canceled.');
|
||||||
|
}).listen(4444, function() {
|
||||||
|
axios.get('http://localhost:4444/', {
|
||||||
|
cancelToken: source.token
|
||||||
|
}).catch(function (thrown) {
|
||||||
|
test.ok(thrown instanceof axios.Cancel, 'Promise must be rejected with a Cancel obejct');
|
||||||
|
test.equal(thrown.message, 'Operation has been canceled.');
|
||||||
|
test.done();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user