简体   繁体   中英

Angularjs promise not resolving in time

I am trying to retrieve data for use in a service that can be used throughout my app. The problem is that I can't get the data to be resolved in time for the routine that uses it. Here is the routine that uses it:

function getTranslation(lookup, language) {

            var i = 0;
            if (vm.translations == null) {

                //vm.translations = getAllTranslations();

                dataService.getTranslations()
              .then(function (data) {
                  vm.translations = data;
              });
            }
            var len = vm.translations.length;
            for (var i=0; i < len; i++) {
                if (vm.translations[i].labelName == lookup) {
                    if (language == "English") {
                        return vm.translations[i].english;
                    } else {
                        if (language == "Spanish") {
                            return vm.translations[i].espanol;
                        }
                    }
                }
            }
            return null;
        }

Here is the calling method within that service:

function getAllTranslations() {
            return vm.translations = dataService.getTranslations()
            .then(function (data) {
                vm.translations = data;
                return vm.translations;
            });

        }

And here is the method in the dataService:

function getTranslations() {
            return $http.get('/api/labeltext')
                .then (getTranslationComplete)
                .catch(getTranslationFailed);
            function getTranslationComplete(response) {
                var deferred = $q.defer();
                return response.data;
            }

            function getTranslationFailed(error) {
                alert("XHR failed for frequent pawner report: " + error.responseText);
            }
        }

I am still learning angularjs and want to be able to populate the data in the service and then call it from other controllers. However, when I get to my for loop the array is empty and only gets populated after its completed.

That is because the promise will not be resolved before your for loop fires. By placing the loop within the .then() , you will have access to the response and your loop values will be defined. This is not DRY since there would be code duplication if you add an else to the function and would have to add in the same loop code. For that, I would refactor the loop into an external function and just call it from within the proper areas of getTranslation() .

    function getTranslation(lookup, language) {

        var i = 0;
        if (vm.translations == null) {

            //vm.translations = getAllTranslations();

            dataService.getTranslations()
          .then(function (data) {
              vm.translations = data;

              var len = vm.translations.length;
              for (var i=0; i < len; i++) {
                if (vm.translations[i].labelName == lookup) {
                    if (language == "English") {
                        return vm.translations[i].english;
                    } else {
                        if (language == "Spanish") {
                            return vm.translations[i].espanol;
                        }
                    }
                }
              }
              });
            }

            return null;
        }

Since your data originates from a promise ( $http ), all of your subsequent code that needs to access that data has to be within a then function.

angular.controller('myController', function(dataService) {
    var translationsPromise;

    /**
     * Caches translations from /api/labeltext and performs a lookup
     * @param lookup
     * @param language
     */
    function getTranslation(lookup, language) {

        if (translationsPromise == null) {
            translationsPromise = dataService.getTranslations()
        }

        translationsPromise.then(function(data) {
            vm.translations = data;

            var len = vm.translations.length;
            for (var i = 0; i < len; i++) {
                if (vm.translations[i].labelName == lookup) {
                    if (language == "English") {
                        return vm.translations[i].english;
                    } else {
                        if (language == "Spanish") {
                            return vm.translations[i].espanol;
                        }
                    }
                }
            }
        });
    }



    getTranslation('Some Label', 'English').then(function(translation) {
        // The translation that was found is accessible in this block
    });

});

When data is asynchronously derived, it's always better to cache a promise rather than the data. Thus, should another request for the same data be made before the original promise is resolved, then that promise can be retrieved from cache, and returned or otherwise exploited. The same is not true of cached async data, which is not guaranteed to have arrived when another request is made.

function getTranslation(lookup, language) {
    if (!vm.translationsPromise) {
        vm.translationsPromise = dataService.getTranslations();
    }
    return vm.translationsPromise.then(function (data) {
        var lang = {'English':'english', 'Spanish':'espanol'};
        return data.reduce(function(str, item) {
            return (str !== '') ? str : (item.labelName == lookup) ? item[lang[language]] : str;
        }, '');
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM