1

I have this function which returns a promise as it's fetching asynchronously data. As you see there are watchers inside the code of that promise ($watchCollection) which keeps watching data and triggers the promise's resolve function for each change.

I can't test whether the then will triggers multiple times once for each resolve function call or not. Is this possible ?

this.getGridDataAndMetaData = function(viewId) {          

    return new Promise(function(resolve, reject) {

        dataStore.fetchView(viewId)
            .then(function(viewEntity) {

                var grid_groupement = viewEntity.descriptor.state ? viewEntity.descriptor.state.grid_groupement : undefined;
                var dataStoreEntities = viewEntity.getEntityType().getEntities();
                var dataStoreProperties = viewEntity.getEntityType().getProperties();

                var gridDataAndMetaData;

                $rootScope.$watchCollection(function() {
                        return dataStoreEntities;
                    },
                    function(newCollection, oldCollection) {    

                        if (!angular.equals(newCollection, {}))
                            formatDataStoreEntities(angular.copy(newCollection), grid_groupement)
                            .then(function(data) {  


                                gridDataAndMetaData = data;                                            

                                if (lastNewProperties != undefined && !angular.equals(lastNewProperties, [])) {
                                    data.viewEntity = viewEntity;
                                    data.grid_groupement = grid_groupement;
                                    data.properties = lastNewProperties;   

                                    resolve(data);
                                }
                            });

                    });

                $rootScope.$watchCollection(function() {
                        return dataStoreProperties;
                    },
                    function(newProperties, oldProperties) {                                    
                        lastNewProperties = angular.copy(newProperties);                                    
                        if (gridDataAndMetaData != undefined && !angular.equals(gridDataAndMetaData.valuesIdsEntitiesTabFormat, {})) {                                                        
                            generateServiceTabs(newProperties, function() {
                                data.viewEntity = viewEntity;
                                data.grid_groupement = grid_groupement;
                                data.properties = lastNewProperties;

                                resolve(data);
                            });
                        }
                    });
            }).catch(function(error) {
                console.error('%c getGridDataAndMetaData :: dataStore.fetchView(viewId):: error : ' + JSON.stringify(error), 'background: red; color: white; display: block;');
                reject(error);
            });


    });

}
georgeawg
  • 48,608
  • 13
  • 72
  • 95
Bardelman
  • 2,176
  • 7
  • 43
  • 70
  • Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Jan 25 '18 at 08:20
  • I have replaced the promise with a callback , i can't test if it will run or not for each data update (= watcher execution). I prefer a callback than using one more library for the observable pattern – Bardelman Jan 25 '18 at 08:24
  • ES6 promises are not AngularJS promises. AngularJS modifies the normal JavaScript flow by providing its own event processing loop. This splits the JavaScript into classical and AngularJS execution context. Only operations which are applied in the AngularJS execution context will benefit from AngularJS data-binding, exception handling, property watching, etc. **Use $q service promises** to bring `.then` blocks into the AngularJS execution context. – georgeawg Jan 25 '18 at 08:28
  • **Don't use watchers inside `.then` blocks**. It will cause memory leaks. What are you trying to accomplish here? – georgeawg Jan 25 '18 at 08:30
  • the returned viewEntity object (by the then()) contains a reference of data and meta data i'm using in my app , i need watchers to be up to date with data changes – Bardelman Jan 25 '18 at 08:32
  • 1
    A Promise (Angular or JavaScript) is only ever settled **once**. Once you've called `resolve` or `reject`, subsequent calls to either of them are completely ignored. You probably want an `Observable` instead, see [this question's answers](https://stackoverflow.com/questions/37364973/angular-promise-vs-observable) for details. – T.J. Crowder Jan 25 '18 at 09:03

1 Answers1

0

resolve function that is the argument of Promise executor function is executed at most once. A Promise can only be fulfilled once. Note, that given dataStore.fetchView(viewId) returns a Promise the Promise constructor is not necessary.

guest271314
  • 1
  • 15
  • 104
  • 177