feat($timeout): pass additional arguments to the callback
Similar to how [`setTimeout`](mdn.io/setTimeout#Syntax) works, this commit allows users of `$timeout` to add additional parameters to the call, which will now be passed on to the callback function. Closes #10631
This commit is contained in:
committed by
Peter Bacon Darwin
parent
41fdb3d536
commit
3a4b6b83ef
+4
-2
@@ -32,6 +32,7 @@ function $TimeoutProvider() {
|
||||
* @param {number=} [delay=0] Delay in milliseconds.
|
||||
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
|
||||
* will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
|
||||
* @param {...*=} Pass additional parameters to the executed function.
|
||||
* @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
|
||||
* promise will be resolved with is the return value of the `fn` function.
|
||||
*
|
||||
@@ -43,14 +44,15 @@ function $TimeoutProvider() {
|
||||
fn = noop;
|
||||
}
|
||||
|
||||
var skipApply = (isDefined(invokeApply) && !invokeApply),
|
||||
var args = sliceArgs(arguments, 3),
|
||||
skipApply = (isDefined(invokeApply) && !invokeApply),
|
||||
deferred = (skipApply ? $$q : $q).defer(),
|
||||
promise = deferred.promise,
|
||||
timeoutId;
|
||||
|
||||
timeoutId = $browser.defer(function() {
|
||||
try {
|
||||
deferred.resolve(fn());
|
||||
deferred.resolve(fn.apply(null, args));
|
||||
} catch (e) {
|
||||
deferred.reject(e);
|
||||
$exceptionHandler(e);
|
||||
|
||||
+57
-10
@@ -22,7 +22,7 @@ describe('$timeout', function() {
|
||||
it('should call $apply after each callback is executed', inject(function($timeout, $rootScope) {
|
||||
var applySpy = spyOn($rootScope, '$apply').andCallThrough();
|
||||
|
||||
$timeout(function() {});
|
||||
$timeout(noop);
|
||||
expect(applySpy).not.toHaveBeenCalled();
|
||||
|
||||
$timeout.flush();
|
||||
@@ -30,8 +30,8 @@ describe('$timeout', function() {
|
||||
|
||||
applySpy.reset();
|
||||
|
||||
$timeout(function() {});
|
||||
$timeout(function() {});
|
||||
$timeout(noop);
|
||||
$timeout(noop);
|
||||
$timeout.flush();
|
||||
expect(applySpy.callCount).toBe(2);
|
||||
}));
|
||||
@@ -40,7 +40,7 @@ describe('$timeout', function() {
|
||||
it('should NOT call $apply if skipApply is set to true', inject(function($timeout, $rootScope) {
|
||||
var applySpy = spyOn($rootScope, '$apply').andCallThrough();
|
||||
|
||||
$timeout(function() {}, 12, false);
|
||||
$timeout(noop, 12, false);
|
||||
expect(applySpy).not.toHaveBeenCalled();
|
||||
|
||||
$timeout.flush();
|
||||
@@ -89,8 +89,8 @@ describe('$timeout', function() {
|
||||
// $browser.defer.cancel is only called on cancel if the deferred object is still referenced
|
||||
var cancelSpy = spyOn($browser.defer, 'cancel').andCallThrough();
|
||||
|
||||
var promise1 = $timeout(function() {}, 0, false);
|
||||
var promise2 = $timeout(function() {}, 100, false);
|
||||
var promise1 = $timeout(noop, 0, false);
|
||||
var promise2 = $timeout(noop, 100, false);
|
||||
expect(cancelSpy).not.toHaveBeenCalled();
|
||||
|
||||
$timeout.flush(0);
|
||||
@@ -104,7 +104,6 @@ describe('$timeout', function() {
|
||||
expect(cancelSpy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
|
||||
it('should allow the `fn` parameter to be optional', inject(function($timeout, log) {
|
||||
|
||||
$timeout().then(function(value) { log('promise success: ' + value); }, log.fn('promise error'));
|
||||
@@ -123,6 +122,35 @@ describe('$timeout', function() {
|
||||
expect(log).toEqual(['promise success: undefined']);
|
||||
}));
|
||||
|
||||
it('should pass the timeout arguments in the timeout callback',
|
||||
inject(function($timeout, $browser, log) {
|
||||
var task1 = jasmine.createSpy('Nappa'),
|
||||
task2 = jasmine.createSpy('Vegeta');
|
||||
|
||||
$timeout(task1, 9000, true, 'What does', 'the timeout', 'say about', 'its delay level');
|
||||
expect($browser.deferredFns.length).toBe(1);
|
||||
|
||||
$timeout(task2, 9001, false, 'It\'s', 'over', 9000);
|
||||
expect($browser.deferredFns.length).toBe(2);
|
||||
|
||||
$timeout(9000, false, 'What!', 9000).then(function(value) { log('There\'s no way that can be right! ' + value); }, log.fn('It can\'t!'));
|
||||
expect($browser.deferredFns.length).toBe(3);
|
||||
expect(log).toEqual([]);
|
||||
|
||||
$timeout.flush(0);
|
||||
expect(task1).not.toHaveBeenCalled();
|
||||
|
||||
$timeout.flush(9000);
|
||||
expect(task1).toHaveBeenCalledWith('What does', 'the timeout', 'say about', 'its delay level');
|
||||
|
||||
$timeout.flush(1);
|
||||
expect(task2).toHaveBeenCalledWith('It\'s', 'over', 9000);
|
||||
|
||||
$timeout.flush(9000);
|
||||
expect(log).toEqual(['There\'s no way that can be right! undefined']);
|
||||
|
||||
}));
|
||||
|
||||
|
||||
describe('exception handling', function() {
|
||||
|
||||
@@ -133,7 +161,7 @@ describe('$timeout', function() {
|
||||
|
||||
it('should delegate exception to the $exceptionHandler service', inject(
|
||||
function($timeout, $exceptionHandler) {
|
||||
$timeout(function() {throw "Test Error";});
|
||||
$timeout(function() { throw "Test Error"; });
|
||||
expect($exceptionHandler.errors).toEqual([]);
|
||||
|
||||
$timeout.flush();
|
||||
@@ -145,7 +173,7 @@ describe('$timeout', function() {
|
||||
function($timeout, $rootScope) {
|
||||
var applySpy = spyOn($rootScope, '$apply').andCallThrough();
|
||||
|
||||
$timeout(function() {throw "Test Error";});
|
||||
$timeout(function() { throw "Test Error"; });
|
||||
expect(applySpy).not.toHaveBeenCalled();
|
||||
|
||||
$timeout.flush();
|
||||
@@ -164,6 +192,25 @@ describe('$timeout', function() {
|
||||
}));
|
||||
|
||||
|
||||
it('should pass the timeout arguments in the timeout callback even if an exception is thrown',
|
||||
inject(function($timeout, log) {
|
||||
var promise1 = $timeout(function(arg) { throw arg; }, 9000, true, 'Some Arguments');
|
||||
var promise2 = $timeout(function(arg1, args2) { throw arg1 + ' ' + args2; }, 9001, false, 'Are Meant', 'To Be Thrown');
|
||||
|
||||
promise1.then(log.fn('success'), function(reason) { log('error: ' + reason); });
|
||||
promise2.then(log.fn('success'), function(reason) { log('error: ' + reason); });
|
||||
|
||||
$timeout.flush(0);
|
||||
expect(log).toEqual('');
|
||||
|
||||
$timeout.flush(9000);
|
||||
expect(log).toEqual('error: Some Arguments');
|
||||
|
||||
$timeout.flush(1);
|
||||
expect(log).toEqual('error: Some Arguments; error: Are Meant To Be Thrown');
|
||||
}));
|
||||
|
||||
|
||||
it('should forget references to relevant deferred even when exception is thrown',
|
||||
inject(function($timeout, $browser) {
|
||||
// $browser.defer.cancel is only called on cancel if the deferred object is still referenced
|
||||
@@ -242,7 +289,7 @@ describe('$timeout', function() {
|
||||
// $browser.defer.cancel is only called on cancel if the deferred object is still referenced
|
||||
var cancelSpy = spyOn($browser.defer, 'cancel').andCallThrough();
|
||||
|
||||
var promise = $timeout(function() {}, 0, false);
|
||||
var promise = $timeout(noop, 0, false);
|
||||
|
||||
expect(cancelSpy).not.toHaveBeenCalled();
|
||||
$timeout.cancel(promise);
|
||||
|
||||
Reference in New Issue
Block a user