diff --git a/src/core/request.js b/src/core/request.js index 527d753..03747fc 100644 --- a/src/core/request.js +++ b/src/core/request.js @@ -14,6 +14,8 @@ function Request(client, queries, callback){ }; this.configure(client, queries, cb); cb = callback = null; + this._activeQueries = []; + this._isAborted = false; }; Emitter(Request.prototype); @@ -35,14 +37,25 @@ Request.prototype.timeout = function(ms){ return this; }; +// Abort all remaining requests +Request.prototype.abort = function(){ + this._isAborted = true; + this._activeQueries.forEach(function(query) { + query.abort(); + }); + this._activeQueries = []; + return this; +} + Request.prototype.refresh = function(){ var self = this, completions = 0, response = [], errored = false; + this._isAborted = false; var handleResponse = function(err, res, index){ - if (errored) { + if (errored || self._isAborted) { return; } if (err) { @@ -62,6 +75,7 @@ Request.prototype.refresh = function(){ self.callback(null, self.data); } } + self._activeQueries.splice(index, 1); }; each(self.queries, function(query, index){ @@ -72,16 +86,16 @@ Request.prototype.refresh = function(){ if (typeof query === 'string') { path += '/saved/' + query + '/result'; - sendSavedQuery.call(self, path, {}, cbSequencer); + self._activeQueries[index] = sendSavedQuery.call(self, path, {}, cbSequencer); } else if (query instanceof Query) { path += '/' + query.analysis; if (query.analysis === 'saved') { path += '/' + query.params.query_name + '/result'; - sendSavedQuery.call(self, path, {}, cbSequencer); + self._activeQueries[index] = sendSavedQuery.call(self, path, {}, cbSequencer); } else { - sendQuery.call(self, path, query.params, cbSequencer); + self._activeQueries[index] = sendQuery.call(self, path, query.params, cbSequencer); } } else { diff --git a/src/core/utils/sendQuery.js b/src/core/utils/sendQuery.js index 73c7806..a6dada0 100644 --- a/src/core/utils/sendQuery.js +++ b/src/core/utils/sendQuery.js @@ -18,19 +18,15 @@ module.exports = function(path, params, callback){ } if (getXHR() || getContext() === 'server' ) { - request + return request .post(url) .set('Content-Type', 'application/json') .set('Authorization', this.client.readKey()) .timeout(this.timeout()) .send(params || {}) - .end(handleResponse); + .end(function handleResponse(err, res){ + responseHandler(err, res, callback); + callback = null; + }); } - - function handleResponse(err, res){ - responseHandler(err, res, callback); - callback = null; - } - - return; } diff --git a/src/core/utils/sendSavedQuery.js b/src/core/utils/sendSavedQuery.js index 61c6c11..6cd97cc 100644 --- a/src/core/utils/sendSavedQuery.js +++ b/src/core/utils/sendSavedQuery.js @@ -2,7 +2,7 @@ var request = require('superagent'); var responseHandler = require('../helpers/superagent-handle-response'); module.exports = function(path, params, callback){ - request + return request .get(this.client.url(path)) .set('Content-Type', 'application/json') .set('Authorization', this.client.readKey()) @@ -12,6 +12,4 @@ module.exports = function(path, params, callback){ responseHandler(err, res, callback); callback = null; }); - - return; } diff --git a/test/unit/modules/core/request/browser-spec.js b/test/unit/modules/core/request/browser-spec.js index ea9065c..7b47a26 100644 --- a/test/unit/modules/core/request/browser-spec.js +++ b/test/unit/modules/core/request/browser-spec.js @@ -100,6 +100,21 @@ describe("Keen.Request", function() { }); }); + describe("abort queries", function() { + it("with multiple queries", function(done) { + var response = [{ result: 1 }, { result: 1 }, { result: 1 }]; + this.server.respondWith( "POST", this.postUrl, [ 200, { "Content-Type": "application/json"}, JSON2.stringify(response[0]) ] ); + this.server.respondWith( "POST", this.postUrl, [ 200, { "Content-Type": "application/json"}, JSON2.stringify(response[1]) ] ); + this.server.respondWith( "POST", this.postUrl, [ 200, { "Content-Type": "application/json"}, JSON2.stringify(response[2]) ] ); + this.server.respond(); + var run = this.client.run([this.query, this.query, this.query], function(err, res){ + expect().fail("callback shouldn't have been called."); + }); + run.abort(); + setTimeout(done, 100); + }); + }); + }); }); diff --git a/test/unit/modules/core/request/server-spec.js b/test/unit/modules/core/request/server-spec.js index 54cf0e2..5cc3b38 100644 --- a/test/unit/modules/core/request/server-spec.js +++ b/test/unit/modules/core/request/server-spec.js @@ -136,6 +136,31 @@ describe("Keen.Request", function() { }); }); + describe("abort queries", function() { + it("with multiple queries", function(done) { + var response = [{ result: 0 }, { result: 1 }, { result: 2 }]; + mock.post("/queries/count", 200, JSON2.stringify(response[0])); + mock.post("/queries/count", 200, JSON2.stringify(response[1])); + mock.post("/queries/count", 200, JSON2.stringify(response[2])); + + var req = new Keen.Request(this.client, [this.query, this.query, this.query], function(err, res){ + expect().fail("callback shouldn't have been called."); + }); + req + .refresh() + .abort(); + setTimeout(done, 100); + }); + + it("with no queries", function(done) { + var req = new Keen.Request(this.client, [], function(err, res){ + expect().fail("callback shouldn't have been called."); + }); + req.refresh().abort(); + done(); + }); + }); + }); });