Snowman
Snowman

Reputation: 32091

How to resolve promise inside Angular $timeout

With callbacks, I wrap the callback in an Angular $timeout block so that it updates the UI.

function makeServerRequest(callback) {
  $timeout(callback);
}

makeServerRequest((response) => {
  $scope.updateUI();
})

This operates within the Angular digest cycle, and the UI gets updated.

However, this doesn't work:

function makeServerRequest() {
  return new Promise((resolve, reject) => {
    $timeout(() => {
      resolve();
    });
  })
}

makeServerRequest().then(() => {
  $scope.updateUI();
})

In this case, it seems like the resolve happens, and then $scope.updateUI(); is called after the timeout.

How can I wrap resolve inside a timeout, so that the outside .then is called inside a timeout?

Upvotes: 0

Views: 956

Answers (2)

georgeawg
georgeawg

Reputation: 48968

What you need to do is create a $q promise from the server request API:

function makeServerRequest() {
  return $q((resolve, reject) => {
     var callback = resolve;
     ServerRequest(callback);
  });  
}

makeServerRequest().then(() => {
  $scope.updateUI();
})

There is no need to use $timeout as the $q Service is integrated with the AngularJS framework and its digest cycle.

For more information, see AngularJS $q Service API Reference - $q constructor.

Upvotes: 0

Estus Flask
Estus Flask

Reputation: 223194

Native Promise doesn't trigger a digest, it should be triggered manually in this case:

makeServerRequest().then(() => {
  $scope.updateUI();
  $scope.$apply()
})

And $timeout already returns a promise ($q promise, which is digest-friendly). So there's no need to create a new one, especially a native one.

It can be:

function makeServerRequest() {
  return $timeout(angular.noop, 100);
}

makeServerRequest().then(...);

Upvotes: 1

Related Questions