From 41cb82a19d3dcae7564ef7ba99701e12c4c7b309 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Tue, 10 Dec 2019 18:40:59 -0600 Subject: [PATCH] Support query.cancel() on Node Moves abort event to prevent xhr.open from calling it. Ensure requestTask is set after the request sends. --- integration/test/ParseQueryTest.js | 13 +++++++++++++ src/ParseQuery.js | 7 +++++-- src/RESTController.js | 28 +++++++++++++++------------- src/__tests__/ParseQuery-test.js | 2 +- 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/integration/test/ParseQueryTest.js b/integration/test/ParseQueryTest.js index a65ee3455..7a5be84bc 100644 --- a/integration/test/ParseQueryTest.js +++ b/integration/test/ParseQueryTest.js @@ -1998,4 +1998,17 @@ describe('Parse Query', () => { }, 0); assert.equal(result, 6); }); + + it('can cancel query', async () => { + const obj1 = new TestObject({ number: 1 }); + const obj2 = new TestObject({ number: 2 }); + const obj3 = new TestObject({ number: 3 }); + await Parse.Object.saveAll([obj1, obj2, obj3]); + + const query = new Parse.Query(TestObject); + query.find().then((results) => { + assert.equal(results.length, 0); + }); + query.cancel(); + }); }); diff --git a/src/ParseQuery.js b/src/ParseQuery.js index b84407dd1..b36414b38 100644 --- a/src/ParseQuery.js +++ b/src/ParseQuery.js @@ -1837,10 +1837,13 @@ class ParseQuery { */ cancel(): ParseQuery { if (this._xhrRequest.task && typeof this._xhrRequest.task.abort === 'function') { + this._xhrRequest.task._aborted = true; this._xhrRequest.task.abort(); + this._xhrRequest.task = null; + this._xhrRequest.onchange = () => {}; + return this; } - this._xhrRequest.task = null; - return this; + return this._xhrRequest.onchange = () => this.cancel(); } _setRequestTask(options) { diff --git a/src/RESTController.js b/src/RESTController.js index 5e89bb78a..385742c22 100644 --- a/src/RESTController.js +++ b/src/RESTController.js @@ -51,9 +51,6 @@ if (typeof XDomainRequest !== 'undefined' && function ajaxIE9(method: string, url: string, data: any, headers?: any, options?: FullOptions) { return new Promise((resolve, reject) => { const xdr = new XDomainRequest(); - if (options && typeof options.requestTask === 'function') { - options.requestTask(xdr); - } xdr.onload = function() { let response; try { @@ -82,6 +79,9 @@ function ajaxIE9(method: string, url: string, data: any, headers?: any, options? }; xdr.open(method, url); xdr.send(data); + if (options && typeof options.requestTask === 'function') { + options.requestTask(xdr); + } }); } @@ -104,14 +104,10 @@ const RESTController = { ); } let handled = false; - let aborted = false; const xhr = new XHR(); - if (options && typeof options.requestTask === 'function') { - options.requestTask(xhr); - } xhr.onreadystatechange = function() { - if (xhr.readyState !== 4 || handled) { + if (xhr.readyState !== 4 || handled || xhr._aborted) { return; } handled = true; @@ -132,8 +128,6 @@ const RESTController = { if (response) { promise.resolve({ response, status: xhr.status, xhr }); } - } else if (aborted && xhr.status === 0) { - promise.resolve({ response: {}, status: 0, xhr }); } else if (xhr.status >= 500 || xhr.status === 0) { // retry on 5XX or node-xmlhttprequest error if (++attempts < CoreManager.get('REQUEST_ATTEMPT_LIMIT')) { // Exponentially-growing random delay @@ -167,9 +161,6 @@ const RESTController = { for (const key in customHeaders) { headers[key] = customHeaders[key]; } - xhr.onabort = () => { - aborted = true; - }; xhr.onprogress = (event) => { if(options && typeof options.progress === 'function') { if (event.lengthComputable) { @@ -184,7 +175,18 @@ const RESTController = { for (const h in headers) { xhr.setRequestHeader(h, headers[h]); } + xhr.onabort = function () { + promise.resolve({ + response: { results: [] }, + status: 0, + xhr, + }); + }; xhr.send(data); + + if (options && typeof options.requestTask === 'function') { + options.requestTask(xhr); + } } dispatch(); diff --git a/src/__tests__/ParseQuery-test.js b/src/__tests__/ParseQuery-test.js index 4452ec9f5..0e7807a7e 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -2124,7 +2124,7 @@ describe('ParseQuery', () => { await query.find(); - expect(query._xhrRequest.task).toEqual(mockRequestTask); + expect(query._xhrRequest.task).toEqual(null); query.cancel(); expect(mockRequestTask.abort).toHaveBeenCalledTimes(1); });