Skip to content

Commit

Permalink
Support query.cancel() (#1003)
Browse files Browse the repository at this point in the history
* Support: query.cancel()

Closes: #997

Taken from Android API [cancel](http://parseplatform.org/Parse-SDK-Android/api/com/parse/ParseQuery.html#cancel--)

Can be improved in the future.

* fix tests

* Add xmlhttprequest note

* remove tests
  • Loading branch information
dplewis authored Nov 23, 2019
1 parent 566f29a commit 728c43e
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 43 deletions.
34 changes: 33 additions & 1 deletion src/ParseQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ class ParseQuery {
_queriesLocalDatastore: boolean;
_localDatastorePinName: any;
_extraOptions: { [key: string]: mixed };
_xhrRequest: any;

/**
* @param {(String|Parse.Object)} objectClass An instance of a subclass of Parse.Object, or a Parse className string.
Expand Down Expand Up @@ -270,6 +271,10 @@ class ParseQuery {
this._queriesLocalDatastore = false;
this._localDatastorePinName = null;
this._extraOptions = {};
this._xhrRequest = {
task: null,
onchange: () => {},
}
}

/**
Expand Down Expand Up @@ -596,6 +601,7 @@ class ParseQuery {
if (options.hasOwnProperty('sessionToken')) {
findOptions.sessionToken = options.sessionToken;
}
this._setRequestTask(findOptions);

const controller = CoreManager.getQueryController();

Expand Down Expand Up @@ -664,6 +670,7 @@ class ParseQuery {
if (options.hasOwnProperty('sessionToken')) {
findOptions.sessionToken = options.sessionToken;
}
this._setRequestTask(findOptions);

const controller = CoreManager.getQueryController();

Expand Down Expand Up @@ -701,12 +708,13 @@ class ParseQuery {
if (options.hasOwnProperty('sessionToken')) {
distinctOptions.sessionToken = options.sessionToken;
}
this._setRequestTask(distinctOptions);

const controller = CoreManager.getQueryController();
const params = {
distinct: key,
where: this._where
};

return controller.aggregate(
this.className,
params,
Expand Down Expand Up @@ -736,6 +744,8 @@ class ParseQuery {
if (options.hasOwnProperty('sessionToken')) {
aggregateOptions.sessionToken = options.sessionToken;
}
this._setRequestTask(aggregateOptions);

const controller = CoreManager.getQueryController();

if (!Array.isArray(pipeline) && typeof pipeline !== 'object') {
Expand Down Expand Up @@ -779,6 +789,7 @@ class ParseQuery {
if (options.hasOwnProperty('sessionToken')) {
findOptions.sessionToken = options.sessionToken;
}
this._setRequestTask(findOptions);

const controller = CoreManager.getQueryController();

Expand Down Expand Up @@ -1817,6 +1828,27 @@ class ParseQuery {
}
return this;
}

/**
* Cancels the current network request (if any is running).
* Note: Support varies based on xmlhttprequest module used. (Will support browser)
*
* @return {Parse.Query} Returns the query, so you can chain this call.
*/
cancel(): ParseQuery {
if (this._xhrRequest.task && typeof this._xhrRequest.task.abort === 'function') {
this._xhrRequest.task.abort();
}
this._xhrRequest.task = null;
return this;
}

_setRequestTask(options) {
options.requestTask = (task) => {
this._xhrRequest.task = task;
this._xhrRequest.onchange();
};
}
}

const DefaultController = {
Expand Down
100 changes: 58 additions & 42 deletions src/__tests__/ParseQuery-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,7 @@ describe('ParseQuery', () => {
size: 'small'
}
});
expect(options).toEqual({});
expect(options.requestTask).toBeDefined();
return Promise.resolve({
results: [
{ objectId: 'I1', size: 'small', name: 'Product 3' }
Expand Down Expand Up @@ -1173,10 +1173,8 @@ describe('ParseQuery', () => {
size: 'small'
}
});
expect(options).toEqual({
useMasterKey: true,
sessionToken: '1234'
});
expect(options.useMasterKey).toEqual(true);
expect(options.sessionToken).toEqual('1234');
return Promise.resolve({
results: []
});
Expand Down Expand Up @@ -1204,7 +1202,7 @@ describe('ParseQuery', () => {
objectId: 'I27'
}
});
expect(options).toEqual({});
expect(options.requestTask).toBeDefined();
return Promise.resolve({
results: [
{ objectId: 'I27', size: 'large', name: 'Product 27' }
Expand Down Expand Up @@ -1237,7 +1235,7 @@ describe('ParseQuery', () => {
objectId: 'I28'
}
});
expect(options).toEqual({});
expect(options.requestTask).toBeDefined();
return Promise.resolve({
results: []
});
Expand Down Expand Up @@ -1267,10 +1265,8 @@ describe('ParseQuery', () => {
objectId: 'I27'
}
});
expect(options).toEqual({
useMasterKey: true,
sessionToken: '1234'
});
expect(options.useMasterKey).toEqual(true);
expect(options.sessionToken).toEqual('1234');
return Promise.resolve({
results: [
{ objectId: 'I27', size: 'large', name: 'Product 27' }
Expand Down Expand Up @@ -1300,7 +1296,7 @@ describe('ParseQuery', () => {
size: 'small'
}
});
expect(options).toEqual({});
expect(options.requestTask).toBeDefined();
return Promise.resolve({
results: [],
count: 145
Expand All @@ -1327,10 +1323,8 @@ describe('ParseQuery', () => {
size: 'small'
}
});
expect(options).toEqual({
useMasterKey: true,
sessionToken: '1234'
});
expect(options.useMasterKey).toEqual(true);
expect(options.sessionToken).toEqual('1234');
return Promise.resolve({
results: [],
count: 145
Expand Down Expand Up @@ -1368,7 +1362,7 @@ describe('ParseQuery', () => {
includeReadPreference: 'SECONDARY',
subqueryReadPreference: 'SECONDARY_PREFERRED',
});
expect(options).toEqual({});
expect(options.requestTask).toBeDefined();
return Promise.resolve({
results: [
{ objectId: 'I55', size: 'medium', name: 'Product 55' },
Expand Down Expand Up @@ -1414,10 +1408,8 @@ describe('ParseQuery', () => {
}
}
});
expect(options).toEqual({
useMasterKey: true,
sessionToken: '1234'
});
expect(options.useMasterKey).toEqual(true);
expect(options.sessionToken).toEqual('1234');
return Promise.resolve({
results: []
});
Expand Down Expand Up @@ -1445,10 +1437,8 @@ describe('ParseQuery', () => {
where: {},
count: 1
});
expect(options).toEqual({
useMasterKey: true,
sessionToken: '1234'
});
expect(options.useMasterKey).toEqual(true);
expect(options.sessionToken).toEqual('1234');
return Promise.resolve({
results:[
{ objectId: '1', name: 'Product 55' },
Expand Down Expand Up @@ -1502,7 +1492,7 @@ describe('ParseQuery', () => {
valid: true
}
});
expect(options).toEqual({});
expect(options.requestTask).toBeDefined();
return Promise.resolve({
results: [
{ objectId: 'I55', size: 'medium', name: 'Product 55' },
Expand Down Expand Up @@ -1549,10 +1539,8 @@ describe('ParseQuery', () => {
valid: true
}
});
expect(options).toEqual({
useMasterKey: true,
sessionToken: '1234'
});
expect(options.useMasterKey).toEqual(true);
expect(options.sessionToken).toEqual('1234');
return Promise.resolve({
results: [
{ objectId: 'I55', size: 'medium', name: 'Product 55' },
Expand Down Expand Up @@ -1964,7 +1952,8 @@ describe('ParseQuery', () => {
size: 'small'
}
});
expect(options).toEqual({ useMasterKey: true });
expect(options.useMasterKey).toEqual(true);
expect(options.requestTask).toBeDefined();
return Promise.resolve({
results: ['L'],
});
Expand All @@ -1989,10 +1978,9 @@ describe('ParseQuery', () => {
size: 'small'
}
});
expect(options).toEqual({
useMasterKey: true,
sessionToken: '1234'
});
expect(options.useMasterKey).toEqual(true);
expect(options.sessionToken).toEqual('1234');
expect(options.requestTask).toBeDefined();
return Promise.resolve({
results: ['L']
});
Expand Down Expand Up @@ -2020,7 +2008,8 @@ describe('ParseQuery', () => {
expect(params).toEqual({
pipeline: [{ group: { objectId: '$name' } }]
});
expect(options).toEqual({ useMasterKey: true });
expect(options.useMasterKey).toEqual(true);
expect(options.requestTask).toBeDefined();
return Promise.resolve({
results: [],
});
Expand All @@ -2045,7 +2034,8 @@ describe('ParseQuery', () => {
expect(params).toEqual({
pipeline: { group: { objectId: '$name' } }
});
expect(options).toEqual({ useMasterKey: true });
expect(options.useMasterKey).toEqual(true);
expect(options.requestTask).toBeDefined();
return Promise.resolve({
results: [],
});
Expand All @@ -2068,7 +2058,8 @@ describe('ParseQuery', () => {
expect(params).toEqual({
group: { objectId: '$name' }
});
expect(options).toEqual({ useMasterKey: true });
expect(options.useMasterKey).toEqual(true);
expect(options.requestTask).toBeDefined();
return Promise.resolve({
results: [],
});
Expand All @@ -2094,10 +2085,8 @@ describe('ParseQuery', () => {
expect(params).toEqual({
pipeline: [{ group: { objectId: '$name' } }]
});
expect(options).toEqual({
useMasterKey: true,
sessionToken: '1234'
});
expect(options.useMasterKey).toEqual(true);
expect(options.sessionToken).toEqual('1234');
return Promise.resolve({
results: []
});
Expand All @@ -2113,6 +2102,33 @@ describe('ParseQuery', () => {
});
});

it('can cancel query', async () => {
const mockRequestTask = {
abort: () => {},
};

CoreManager.setQueryController({
find: function(name, params, options) {
options.requestTask(mockRequestTask);
return Promise.resolve({
results: []
});
},
aggregate: () => {},
});
const query = new ParseQuery('TestCancel');

jest.spyOn(mockRequestTask, 'abort');
query.cancel();
expect(mockRequestTask.abort).toHaveBeenCalledTimes(0);

await query.find();

expect(query._xhrRequest.task).toEqual(mockRequestTask);
query.cancel();
expect(mockRequestTask.abort).toHaveBeenCalledTimes(1);
});

it('selecting sub-objects does not inject objects when sub-object does not exist', (done) => {
jest.dontMock("../ParseObject");
jest.resetModules();
Expand Down

0 comments on commit 728c43e

Please sign in to comment.