How to delay a promise in when function
To delay a promise, simply call the resolve
function after a wait time.
new Promise(function(resolve, reject) { setTimeout(function() { resolve(); }, 3000); // Wait 3s then resolve.});
The issue with your code is that you are returning a Promise and then inside the then
of that Promise you are creating another one and expecting the original promise to wait for it - I'm afraid that's not how promises work. You would have to do all your waiting inside the promise function and then call resolve:
Edit: This is not true, you can delay the promise chain in any then
:
function promise1() { return new Promise((resolve) => { setTimeout(() => { console.log('promise1'); resolve(); }, 1000); }) .then(promise2);}function promise2() { return new Promise((resolve) => { setTimeout(() => { console.log('promise2'); resolve(); }, 1000); });}function promise3() { return new Promise((resolve) => { setTimeout(() => { console.log('promise3'); resolve(); }, 1000); });}promise1() .then(promise3) .then(() => { console.log('...finished'); })
However that is not a good way to wait for a css animation. It's better to listen to the transitionend event:
element.addEventListener('transitionend', onTransitionEnd);element.classList.add('transition-me');
Note if you're using an animation
instead of a transition
the same concept applies but use the animationend event.
Each then
accepts a function which should return a Promise. It does not accept an instance of Promise. You want to return the call to timeout
:
return MyService .getData(viewId) .then(function(data) { // ... }) .then(function () { return timeout(3000); });
Alternatively, have timeout
return a function instead of a Promise:
function timeout(delay) { return function () { return new Promise(function(resolve, reject) { // ^^^^^^^ (misspelt in your example) $timeout(resolve, delay); }); };}
And then you can use it as in your example:
return MyService .getData(viewId) .then(function(data) { // ... }) .then(timeout(3000));
How can I delay a chain of promises?
$timeout
returns a promise. Return that promise to chain it.
$scope.openView = function (viewId) { // Check if view is already open if ($scope.viewId == viewId) { //chain right away with empty promise return $q.when(); }; //otherwise if view is not already open var p = MyService.getData(viewId).then(function(data) { // add data to view // change class to open view // this is working ok! }); var pDelayed = p.then (function () { //return to chain delay return $timeout(angular.noop, 30000); }); //return delayed promise for chaining return pDelayed;};$scope.openView(viewId).then(function() { //use chained promise $scope.openAnotherView(anotherViewId);});