在 Angular 1.6 中,如何在控制器内部的 $scope 中使用多个 json 正确获取配置数据?

In Angular 1.6, how to get properly config data from several json using in $scope inside controller?

我想在我的控制器中的 $scope 中加载 2 json 数据,然后再执行类似基本案例的操作。但是 $http 在我的工厂中 return 是状态对象,因为它 return 是一个承诺。

我的供应商作为工厂对象

(function(angular) {
   'use strict';
    angular.module('myModule').factory("config", function($http) {
        return{
            getConfig: function () {
                return $http.get('json/config.json').then(function(response) {
                    return response.data;
               });
            },
            getPreferences:  function () {
                return $http.get('json/preferences.json').then(function(response) {
                     return response.data;
                });
           }
      }; 
   }); 
})(window.angular);

如何将来自多个文件的所有外部 json 数据存储在主控制器内的 $scope 变量中而不超时或添加多个嵌套 promise.then ?实际上,我想知道是否有一种方法可以在控制器加载之前存储所有 json 数据?

(function(angular) {
    'use strict';
    angular.module('myModule')
    .controller('MainCtrl', ['$scope', 'config', function ($scope, config, ){
        $scope.config = ?????????? ;
        $scope.preferences = ???????????? ;             
     }]);
})(window.angular);

只需在您的控制器中从您的服务 config 调用您的方法...

(function(angular) {
    'use strict';
    angular.module('myModule')
    .controller('MainCtrl', ['$scope', 'config', '$q', function ($scope, config, $q) { 
       config.getConfig().then(function(data) {
         $scope.config = data;
       });
       config.getPreferences().then(function(data) {
         $scope.preferences = data;
       });

       // or if you want, 
       // you can wait for the both requests to finish and get them at once
       $q.all([
            config.getConfig(),
            config.getPreferences()
       ])
       .then(function(responses) {
          $scope.config = responses[0];
          $scope.preferences = responses[1];
       });
     }]);
})(window.angular);

如果您在控制器初始化之前需要此配置数据并且您正在使用路由器,您可以从路由器解析它,并且在您的控制器被触发时可用。

路由器

  $stateProvider
    .state('stateName', {
      url: '/stateURL',
      templateUrl: 'path/to/the/template',
      controller: 'MainCtrl',
      resolve: {
        configData: ['$q', config, function ($q, config) {
          return $q.all([
            config.getConfig(),
            config.getPreferences()
          ]);
       }
     }
   });

控制器

(function(angular) {
  'use strict';
  angular.module('myModule')
    .controller('MainCtrl', ['$scope', 'configData', function ($scope, configData) {
      $scope.config = configData[0];
      $scope.preferences = configData[1];
  }]);

已编辑

只需调用您的 getConfig 函数并使用 returned 承诺:

config.getConfig()
    .then(function(data) {
        // In your config factory you choose to return reponse.data so in this callback data = response.data
        $scope.config = data
     }

config.getPreferences()
    .then(function(data) {
        // In your config factory you choose to return reponse.data so in this callback data = response.data
        $scope.preferences = data
     }

在您的工厂中,您 return 一个承诺并将其配置为使用 response.data 解析,因此当您解析 returned 承诺时,该字段将直接 returned。

My problem is when I have to get two json data, I should do promise.then inside a promise.then. I would like to find a solution to load all json data before execute my code in controller

使用$q.all等待几个promise完成:

var configPromise = config.getConfig();
var prefPromise = config.getPreferences();

$q.all([configPromise, prefPromise]).then(function(dataList) {
    $scope.config = dataList[0];
    $scope.preferences = dataList[1];

    console.log($scope.config);
    console.log($scope.preferences);

    //Put more code here
});
        

有关详细信息,请参阅 AngularJS $q Service API Reference - $q.all


If you do console.log($scope.config) outside the getConfig function, it's wrong because it's undefined.

这就是异步 API 的工作方式。成功处理程序中的代码在 .then 方法外部的所有代码之后执行。

将console.log放在处理函数中:

config.getConfig().then(function successHandler(data) {
    $scope.config = data
    //HERE
    console.log($scope.config);
};

//NOT HERE
 ̶c̶o̶n̶s̶o̶l̶e̶.̶l̶o̶g̶(̶$̶s̶c̶o̶p̶e̶.̶c̶o̶n̶f̶i̶g̶)̶;̶

基于 Promise 的异步操作的解释

console.log("Part1");
console.log("Part2");
var promise = $http.get(url);
promise.then(function successHandler(response){
    console.log("Part3");
});
console.log("Part4");

“第 4 部分”的控制台日志不必等待数据从服务器返回。它在 XHR starts 后立即执行。 “第 3 部分”的控制台日志位于 $q service 持有的成功处理函数中,并在 数据从服务器和 XHR 到达后调用 完成.

有关详细信息,请参阅


演示

console.log("Part 1");
console.log("Part 2");
var promise = new Promise(r=>r());
promise.then(function() {
    console.log("Part 3");
});
console.log("Part *4*");