Mik378
Mik378

Reputation: 22171

Is there a real difference between $interval and $timeout in this use case?

Is there a real difference between:

$interval(function () {
  doSomething();
}, 250, 1, true);

and

$timeout(function () {
  doSomething();
}, 250);

The only possible difference I could notice is that I could bypass a digest cycle if I use false for the last parameter of $interval.

Upvotes: 1

Views: 658

Answers (2)

Michelle Tilley
Michelle Tilley

Reputation: 159105

There are differences, but none around the points mentioned in the question. Namely, $timeout's promise resolves to the return value of the deferred function, and if the function throws an exception the promise is rejected with the exception. $interval's promise delivers notify events, and is eventually resolved with the current iteration count if a maximum number of iterations is specified and it is eventually reached. In addition, the function passed to $interval receives the current iteration as an argument, and Angular does nothing with exceptions thrown from inside the function.

Consider the following code:

$timeout(function() {
  return "first";
}, 100).then(function(value) {
  // logs "Timeout resolved to: first"
  console.log("Timeout resolved to: " + value);
});

$interval(function(iteration) {
  // logs 0, 1, 2, 3, and 4
  console.log(iteration);
  return "second";
}, 20, 5).then(function(value) {
  // logs "Interval resolved to: 5"
  console.log("Interval resolved to: " + value);
});

Upvotes: 0

Krzysztof Safjanowski
Krzysztof Safjanowski

Reputation: 7438

Let’s do some code analysis

Timeout

function timeout(fn, delay, invokeApply) {
  var deferred = $q.defer(),
      promise = deferred.promise,
      skipApply = (isDefined(invokeApply) && !invokeApply),
      timeoutId;

  timeoutId = $browser.defer(function() {
    try {
      deferred.resolve(fn());
    } catch(e) {
      deferred.reject(e);
      $exceptionHandler(e);
    }
    finally {
      delete deferreds[promise.$$timeoutId];
    }

    if (!skipApply) $rootScope.$apply();
  }, delay);

  promise.$$timeoutId = timeoutId;
  deferreds[timeoutId] = deferred;

  return promise;
}

Interval

function interval(fn, delay, count, invokeApply) {
  var setInterval = $window.setInterval,
      clearInterval = $window.clearInterval,
      deferred = $q.defer(),
      promise = deferred.promise,
      iteration = 0,
      skipApply = (isDefined(invokeApply) && !invokeApply);

  count = isDefined(count) ? count : 0;

  promise.then(null, null, fn);

  promise.$$intervalId = setInterval(function tick() {
    deferred.notify(iteration++);

    if (count > 0 && iteration >= count) {
      deferred.resolve(iteration);
      clearInterval(promise.$$intervalId);
      delete intervals[promise.$$intervalId];
    }

    if (!skipApply) $rootScope.$apply();

  }, delay);

  intervals[promise.$$intervalId] = deferred;

  return promise;
}

Last difference is not true as both of methods implements if (!skipApply) $rootScope.$apply(); There is no difference.

Upvotes: 1

Related Questions