我最近发布了一篇关于我在SO面临的问题的详细描述。由于我无法发送一个实际的$http请求,所以我使用timeout来模拟异步行为。在@Gloopy的帮助下,从我的模型到视图的数据绑定工作正常

现在,当我使用$http而不是$timeout(在本地测试)时,我可以看到异步请求是成功的,数据在我的服务中被json响应填充。但是,我的观点并没有更新。

在这里更新Plunkr


当前回答

请尝试下面的代码

你可以分离控制器(PageCtrl)和服务(dataService)

'use strict'; (function () { angular.module('myApp') .controller('pageContl', ['$scope', 'dataService', PageContl]) .service('dataService', ['$q', '$http', DataService]); function DataService($q, $http){ this.$q = $q; this.$http = $http; //... blob blob } DataService.prototype = { getSearchData: function () { var deferred = this.$q.defer(); //initiating promise this.$http({ method: 'POST',//GET url: 'test.json', headers: { 'Content-Type': 'application/json' } }).then(function(result) { deferred.resolve(result.data); },function (error) { deferred.reject(error); }); return deferred.promise; }, getABCDATA: function () { } }; function PageContl($scope, dataService) { this.$scope = $scope; this.dataService = dataService; //injecting service Dependency in ctrl this.pageData = {}; //or []; } PageContl.prototype = { searchData: function () { var self = this; //we can't access 'this' of parent fn from callback or inner function, that's why assigning in temp variable this.dataService.getSearchData().then(function (data) { self.searchData = data; }); } } }());

其他回答

我认为更好的方式是这样的:

服务:

app.service('FruitsManager',function($q){

    function getAllFruits(){
        var deferred = $q.defer();

        ...

        // somewhere here use: deferred.resolve(awesomeFruits);

        ...

        return deferred.promise;
    }

    return{
        getAllFruits:getAllFruits
    }

});

在控制器中,你可以简单地使用:

$scope.fruits = FruitsManager.getAllFruits();

Angular会自动把解析后的awesomfruits放到$scope.fruits中。

至于在服务中缓存响应,这里有另一个版本,似乎比我目前看到的更直接:

App.factory('dataStorage', function($http) {
     var dataStorage;//storage for cache

     return (function() {
         // if dataStorage exists returned cached version
        return dataStorage = dataStorage || $http({
      url: 'your.json',
      method: 'GET',
      cache: true
    }).then(function (response) {

              console.log('if storage don\'t exist : ' + response);

              return response;
            });

    })();

});

该服务将返回缓存的数据或$http.get;

 dataStorage.then(function(data) {
     $scope.data = data;
 },function(e){
    console.log('err: ' + e);
 });

请尝试下面的代码

你可以分离控制器(PageCtrl)和服务(dataService)

'use strict'; (function () { angular.module('myApp') .controller('pageContl', ['$scope', 'dataService', PageContl]) .service('dataService', ['$q', '$http', DataService]); function DataService($q, $http){ this.$q = $q; this.$http = $http; //... blob blob } DataService.prototype = { getSearchData: function () { var deferred = this.$q.defer(); //initiating promise this.$http({ method: 'POST',//GET url: 'test.json', headers: { 'Content-Type': 'application/json' } }).then(function(result) { deferred.resolve(result.data); },function (error) { deferred.reject(error); }); return deferred.promise; }, getABCDATA: function () { } }; function PageContl($scope, dataService) { this.$scope = $scope; this.dataService = dataService; //injecting service Dependency in ctrl this.pageData = {}; //or []; } PageContl.prototype = { searchData: function () { var self = this; //we can't access 'this' of parent fn from callback or inner function, that's why assigning in temp variable this.dataService.getSearchData().then(function (data) { self.searchData = data; }); } } }());

这里有一个Plunk,可以做你想要的:http://plnkr.co/edit/TTlbSv?p=preview

其思想是直接使用承诺及其“then”函数来操作和访问异步返回的响应。

app.factory('myService', function($http) {
  var myService = {
    async: function() {
      // $http returns a promise, which has a then function, which also returns a promise
      var promise = $http.get('test.json').then(function (response) {
        // The then function here is an opportunity to modify the response
        console.log(response);
        // The return value gets picked up by the then in the controller.
        return response.data;
      });
      // Return the promise to the controller
      return promise;
    }
  };
  return myService;
});

app.controller('MainCtrl', function( myService,$scope) {
  // Call the async method and then do stuff with what is returned inside our own then function
  myService.async().then(function(d) {
    $scope.data = d;
  });
});

这里有一个稍微复杂一点的版本,它缓存了请求,所以您只在第一次发出请求(http://plnkr.co/edit/2yH1F4IMZlMS8QsV9rHv?p=preview):

app.factory('myService', function($http) {
  var promise;
  var myService = {
    async: function() {
      if ( !promise ) {
        // $http returns a promise, which has a then function, which also returns a promise
        promise = $http.get('test.json').then(function (response) {
          // The then function here is an opportunity to modify the response
          console.log(response);
          // The return value gets picked up by the then in the controller.
          return response.data;
        });
      }
      // Return the promise to the controller
      return promise;
    }
  };
  return myService;
});

app.controller('MainCtrl', function( myService,$scope) {
  $scope.clearData = function() {
    $scope.data = {};
  };
  $scope.getData = function() {
    // Call the async method and then do stuff with what is returned inside our own then function
    myService.async().then(function(d) {
      $scope.data = d;
    });
  };
});

与此相关,我也遇到过类似的问题,但不是用Angular的get或post,而是用第三方的扩展(在我的例子中是Chrome extension)。 我面临的问题是,Chrome扩展不会返回然后(),所以我无法做到上面的解决方案,但结果仍然是异步的。 因此,我的解决方案是创建一个服务,然后进行回调

app.service('cookieInfoService', function() {
    this.getInfo = function(callback) {
        var model = {};
        chrome.cookies.get({url:serverUrl, name:'userId'}, function (response) {
            model.response= response;
            callback(model);
        });
    };
});

然后在控制器中

app.controller("MyCtrl", function ($scope, cookieInfoService) {
    cookieInfoService.getInfo(function (info) {
        console.log(info);
    });
});

希望这篇文章可以帮助其他有同样问题的人。