mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-12 17:03:09 +00:00
feat($browser.$defer.cancel): support canceling defered tasks
This commit is contained in:
parent
120701b9d9
commit
2b2df4754d
3 changed files with 86 additions and 11 deletions
|
|
@ -40,6 +40,8 @@ function Browser(window, document, body, XHR, $log) {
|
||||||
rawDocument = document[0],
|
rawDocument = document[0],
|
||||||
location = window.location,
|
location = window.location,
|
||||||
setTimeout = window.setTimeout,
|
setTimeout = window.setTimeout,
|
||||||
|
clearTimeout = window.clearTimeout,
|
||||||
|
pendingDeferIds = {},
|
||||||
lastLocationUrl;
|
lastLocationUrl;
|
||||||
|
|
||||||
self.isMock = false;
|
self.isMock = false;
|
||||||
|
|
@ -163,15 +165,12 @@ function Browser(window, document, body, XHR, $log) {
|
||||||
* @returns {function()} the added function
|
* @returns {function()} the added function
|
||||||
*/
|
*/
|
||||||
self.addPollFn = function(fn) {
|
self.addPollFn = function(fn) {
|
||||||
if (!pollTimeout) startPoller(100, setTimeout);
|
if (isUndefined(pollTimeout)) startPoller(100, setTimeout);
|
||||||
pollFns.push(fn);
|
pollFns.push(fn);
|
||||||
return fn;
|
return fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name angular.service.$browser#startPoller
|
|
||||||
* @methodOf angular.service.$browser
|
|
||||||
*
|
|
||||||
* @param {number} interval How often should browser call poll functions (ms)
|
* @param {number} interval How often should browser call poll functions (ms)
|
||||||
* @param {function()} setTimeout Reference to a real or fake `setTimeout` function.
|
* @param {function()} setTimeout Reference to a real or fake `setTimeout` function.
|
||||||
*
|
*
|
||||||
|
|
@ -339,20 +338,49 @@ function Browser(window, document, body, XHR, $log) {
|
||||||
* @methodOf angular.service.$browser
|
* @methodOf angular.service.$browser
|
||||||
* @param {function()} fn A function, who's execution should be defered.
|
* @param {function()} fn A function, who's execution should be defered.
|
||||||
* @param {number=} [delay=0] of milliseconds to defer the function execution.
|
* @param {number=} [delay=0] of milliseconds to defer the function execution.
|
||||||
|
* @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
* Executes a fn asynchroniously via `setTimeout(fn, delay)`.
|
* Executes a fn asynchroniously via `setTimeout(fn, delay)`.
|
||||||
*
|
*
|
||||||
* Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
|
* Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
|
||||||
* `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed via
|
* `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
|
||||||
* `$browser.defer.flush()`.
|
* via `$browser.defer.flush()`.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
self.defer = function(fn, delay) {
|
self.defer = function(fn, delay) {
|
||||||
|
var timeoutId;
|
||||||
outstandingRequestCount++;
|
outstandingRequestCount++;
|
||||||
setTimeout(function() { completeOutstandingRequest(fn); }, delay || 0);
|
timeoutId = setTimeout(function() {
|
||||||
|
delete pendingDeferIds[timeoutId];
|
||||||
|
completeOutstandingRequest(fn);
|
||||||
|
}, delay || 0);
|
||||||
|
pendingDeferIds[timeoutId] = true;
|
||||||
|
return timeoutId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @workInProgress
|
||||||
|
* @ngdoc method
|
||||||
|
* @name angular.service.$browser.defer#cancel
|
||||||
|
* @methodOf angular.service.$browser.defer
|
||||||
|
* @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Cancels a defered task identified with `deferId`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
self.defer.cancel = function(deferId) {
|
||||||
|
if (pendingDeferIds[deferId]) {
|
||||||
|
delete pendingDeferIds[deferId];
|
||||||
|
clearTimeout(deferId);
|
||||||
|
completeOutstandingRequest(noop);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
// Misc API
|
// Misc API
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
19
src/angular-mocks.js
vendored
19
src/angular-mocks.js
vendored
|
|
@ -281,15 +281,32 @@ function MockBrowser() {
|
||||||
self.cookieHash = {};
|
self.cookieHash = {};
|
||||||
self.lastCookieHash = {};
|
self.lastCookieHash = {};
|
||||||
self.deferredFns = [];
|
self.deferredFns = [];
|
||||||
|
self.deferredNextId = 0;
|
||||||
|
|
||||||
self.defer = function(fn, delay) {
|
self.defer = function(fn, delay) {
|
||||||
delay = delay || 0;
|
delay = delay || 0;
|
||||||
self.deferredFns.push({time:(self.defer.now + delay), fn:fn});
|
self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});
|
||||||
self.deferredFns.sort(function(a,b){ return a.time - b.time;});
|
self.deferredFns.sort(function(a,b){ return a.time - b.time;});
|
||||||
|
return self.deferredNextId++;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
self.defer.now = 0;
|
self.defer.now = 0;
|
||||||
|
|
||||||
|
|
||||||
|
self.defer.cancel = function(deferId) {
|
||||||
|
var fnIndex;
|
||||||
|
|
||||||
|
forEach(self.deferredFns, function(fn, index) {
|
||||||
|
if (fn.id === deferId) fnIndex = index;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (fnIndex) {
|
||||||
|
self.deferredFns.splice(fnIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
self.defer.flush = function(delay) {
|
self.defer.flush = function(delay) {
|
||||||
if (angular.isDefined(delay)) {
|
if (angular.isDefined(delay)) {
|
||||||
self.defer.now += delay;
|
self.defer.now += delay;
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,11 @@ describe('browser', function(){
|
||||||
var browser, fakeWindow, xhr, logs, scripts, removedScripts, setTimeoutQueue;
|
var browser, fakeWindow, xhr, logs, scripts, removedScripts, setTimeoutQueue;
|
||||||
|
|
||||||
function fakeSetTimeout(fn) {
|
function fakeSetTimeout(fn) {
|
||||||
setTimeoutQueue.push(fn);
|
return setTimeoutQueue.push(fn) - 1; //return position in the queue
|
||||||
return Math.random();
|
}
|
||||||
|
|
||||||
|
function fakeClearTimeout(deferId) {
|
||||||
|
setTimeoutQueue[deferId] = noop; //replace fn with noop to preserve other deferId indexes
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeSetTimeout.flush = function() {
|
fakeSetTimeout.flush = function() {
|
||||||
|
|
@ -25,7 +28,8 @@ describe('browser', function(){
|
||||||
xhr = null;
|
xhr = null;
|
||||||
fakeWindow = {
|
fakeWindow = {
|
||||||
location: {href:"http://server"},
|
location: {href:"http://server"},
|
||||||
setTimeout: fakeSetTimeout
|
setTimeout: fakeSetTimeout,
|
||||||
|
clearTimeout: fakeClearTimeout
|
||||||
};
|
};
|
||||||
|
|
||||||
var fakeBody = [{appendChild: function(node){scripts.push(node);},
|
var fakeBody = [{appendChild: function(node){scripts.push(node);},
|
||||||
|
|
@ -161,6 +165,32 @@ describe('browser', function(){
|
||||||
fakeSetTimeout.flush();
|
fakeSetTimeout.flush();
|
||||||
expect(callback).toHaveBeenCalled();
|
expect(callback).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should return unique deferId', function() {
|
||||||
|
var deferId1 = browser.defer(noop),
|
||||||
|
deferId2 = browser.defer(noop);
|
||||||
|
|
||||||
|
expect(deferId1).toBeDefined();
|
||||||
|
expect(deferId2).toBeDefined();
|
||||||
|
expect(deferId1).not.toEqual(deferId2);
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
describe('cancel', function() {
|
||||||
|
it('should allow tasks to be canceled with returned deferId', function() {
|
||||||
|
var log = [],
|
||||||
|
deferId1 = browser.defer(function() { log.push('cancel me') }),
|
||||||
|
deferId2 = browser.defer(function() { log.push('ok') }),
|
||||||
|
deferId3 = browser.defer(function() { log.push('cancel me, now!') });
|
||||||
|
|
||||||
|
expect(log).toEqual([]);
|
||||||
|
browser.defer.cancel(deferId1);
|
||||||
|
browser.defer.cancel(deferId3);
|
||||||
|
fakeSetTimeout.flush();
|
||||||
|
expect(log).toEqual(['ok']);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue