【问题标题】:Angularjs promise not resolving in timeAngularjs承诺不会及时解决
【发布时间】:2016-01-24 02:12:29
【问题描述】:

我正在尝试检索可在整个应用程序中使用的服务中使用的数据。问题是我无法为使用它的例程及时解决数据。这是使用它的例程:

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;
        }

这是该服务中的调用方法:

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

        }

这是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);
            }
        }

我还在学习 angularjs,希望能够在服务中填充数据,然后从其他控制器调用它。但是,当我进入我的 for 循环时,数组是空的,只有在完成后才会填充。

【问题讨论】:

  • 调用什么代码getTranslation()
  • 如果 API 返回异步数据,它需要在整个应用程序中保持异步。换句话说,您总是需要使用.then 来获取数据。或者,查看ui.router/ngRoute 路由器 - 它们支持resolve 参数,该参数基本上等待加载数据已加载下的状态/路由

标签: javascript angularjs promise angularjs-service


【解决方案1】:

当数据是异步派生的时,缓存 Promise 总是比缓存数据更好。因此,如果在解决原始承诺之前对相同数据发出另一个请求,则可以从缓存中检索该承诺,并返回或以其他方式利用。缓存的异步数据并非如此,当发出另一个请求时,不能保证已经到达。

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;
        }, '');
    });
}

【讨论】:

    【解决方案2】:

    由于您的数据源自一个承诺 ($http),因此需要访问该数据的所有后续代码都必须位于 then 函数中。

    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
        });
    
    });
    

    【讨论】:

      【解决方案3】:

      这是因为在你的 for 循环触发之前,promise 不会被解决。通过将循环放在.then() 中,您将可以访问响应并定义您的循环值。这不是 DRY,因为如果将 else 添加到函数中会出现代码重复,并且必须添加相同的循环代码。为此,我会将循环重构为一个外部函数,然后从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;
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-09
        • 2016-05-06
        • 2015-07-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多