AngularJS promise is not resolved multiple times using $interval
Asked Answered
S

2

6

Surprised to see why the angularjs promise is not resolved multiple times using $interval service. Below is my code. The variable i is incremented multiple times, however the promise is resolved only once.

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, myService) {
    myService.then(function(result) {
        $scope.i = result;
    });
});
app.factory('myService', function($interval, $q) {
    var deferred = $q.defer();
    var i = 0;
    $interval(function() {
        i += 1;
        deferred.resolve(i);
    }, 2000);
    return deferred.promise;
});

Plunker

Swaim answered 2/10, 2014 at 9:54 Comment(1)
Hmm instead of using an external library, you can use it like this instead? PLUNKERDictaphone
W
5

Using AngularJS, you can use the notify feature of $q (https://docs.angularjs.org/api/ng/service/$q) instead of resolve:

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, myService) {
    // Notice that the third callback is for notify
    myService.then(null, null, function(result) {
        $scope.i = result;
    });
});
app.factory('myService', function($interval, $q) {
    var deferred = $q.defer();
    var i = 0;
    $interval(function() {
        i += 1;
        deferred.notify(i);
    }, 2000);
    return deferred.promise;
});

You might want to add a $interval.cancel() to stop the loop at some point/condition (https://docs.angularjs.org/api/ng/service/$interval).

Winni answered 21/8, 2015 at 16:37 Comment(1)
Thanks, didn't knew about notify.Swaim
T
6

A promise represents a single deferred value. It will not resolve more than once.

If you want similar functionality for streams of events, check out Rx.JS

With Rx your code would look similar:

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, myService) {
    myService.subscribe(function(result) {
        $scope.i = result;
    });
});
app.factory('myService', function($interval, $q) {
    var subject = new Rx.Subject();
    var i = 0;
    $interval(function() {
        i += 1;
        subject.onNext(i);
    }, 2000);
    return subject;
});
Tuning answered 2/10, 2014 at 9:58 Comment(1)
Thanks, Alex. Didn't knew about Rx.JS. Thanks.Swaim
W
5

Using AngularJS, you can use the notify feature of $q (https://docs.angularjs.org/api/ng/service/$q) instead of resolve:

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, myService) {
    // Notice that the third callback is for notify
    myService.then(null, null, function(result) {
        $scope.i = result;
    });
});
app.factory('myService', function($interval, $q) {
    var deferred = $q.defer();
    var i = 0;
    $interval(function() {
        i += 1;
        deferred.notify(i);
    }, 2000);
    return deferred.promise;
});

You might want to add a $interval.cancel() to stop the loop at some point/condition (https://docs.angularjs.org/api/ng/service/$interval).

Winni answered 21/8, 2015 at 16:37 Comment(1)
Thanks, didn't knew about notify.Swaim

© 2022 - 2024 — McMap. All rights reserved.