Angular 1.6.6:控制器$http迁移至Factory后$scope数据绑定异常
Hey there, I can spot the issue right away—you're running into a common pitfall with Promises in Angular, and your controller isn't properly handling the Promise returned by your Factory. Let's fix this together!
What's Going Wrong
When you moved your $http call to the Factory, you’re returning a Promise from getAllDBRegions(), but in your controller, you’re directly assigning that Promise to $scope.regions instead of waiting for it to resolve and extracting the actual data. Angular can’t bind a Promise object to your view, which is why you see the data in the debugger but it doesn’t show up in your template.
Also, a quick cleanup: you don’t need to manually create a $q.defer() here—$http already returns a Promise, so we can simplify your Factory code to avoid that anti-pattern.
Step 1: Simplify the Factory Code
Let’s rewrite the Factory to return the $http Promise directly, and make sure we pass the correct data when resolving:
angular.module('randomTown.service', []) .factory('randomTownFactory', function ($http) { var service = {}; service.getAllDBRegions = function() { // $http already returns a Promise, no need for $q.defer() return $http({ method: 'GET', url: '/all-regions' }).then(function success(response) { // Return the actual data (response.data) instead of the full response object return response.data; }, function error(response) { // Reject with a meaningful error message return Promise.reject('There was an error fetching regions: ' + response.statusText); }); }; return service; });
Step 2: Fix the Controller to Handle the Promise
Now update your controller to wait for the Promise to resolve before assigning data to $scope.regions:
angular.module('randomTown.controller', []) .component('randomTownGenerator', { templateUrl: 'js/components/randomTownGenerator/randomTownGenerator.tpl.html' }) .controller('RandomTownCtrl', function($scope, randomTownFactory) { $scope.data = {}; $scope.getAllRegions = function () { // Call the Factory method, then handle the resolved Promise randomTownFactory.getAllDBRegions() .then(function(regionsData) { // Assign the actual data to $scope.regions $scope.regions = regionsData; }) .catch(function(error) { // Handle any errors here (optional but recommended) console.error(error); }); }; });
Why This Works
- The Factory now returns the
$httpPromise directly, which is cleaner and avoids unnecessary$qusage. - In the controller, we use
.then()to wait for the Promise to successfully resolve, then assign the actual region data to$scope.regions. This ensures the data is available when Angular goes to bind it to your template. - We also added a
.catch()block to handle errors, which is a good practice for debugging and user feedback.
Your template doesn’t need any changes—once $scope.regions is populated with the actual array of region objects, ng-options will render the options correctly.
内容的提问来源于stack exchange,提问作者Nate Anderson

