【问题标题】:Angular Service - Pass $http data to scopeAngular Service - 将 $http 数据传递给范围
【发布时间】:2015-02-08 15:20:24
【问题描述】:

我正在尝试在 Service 内部创建一个角度函数,以通过 $http 返回访问数据,然后返回到所需的范围。

所以我的服务是这样的;

app.service('agrService', function ($http) {

    this.testinho = function(){
        return "teste";
    }

    this.bannerSlides = function(){

        var dataUrl = "data/banner-rotator.json";

        // Simple GET request example :
        $http({
            method: 'GET',
            dataType: "json",
            url: dataUrl
        })
        .success( function(data, status, headers, config) {

            // this callback will be called asynchronously
            // when the response is available

            //console.log(data);
            return data;

        }).error( function(data, status, headers, config) {

            // called asynchronously if an error occurs
            // or server returns response with an error status.
            alert("Niente, Nada, Caput");
        });

    }

})

然后我想将返回的数据与我的主 App 控制器内的范围相关联......就像这样:

app.controller('AppCtrl', function($scope, $http, agrService) {
    $scope.slides = agrService.bannerSlides();
})

然后在我的模板中,我想像这样循环数据:

<div ng-repeat="slide in slides">
    <div class="box" style="background: url('{{ slide.url }}') no-repeat center;"></div>
</div>

问题是数据只有在成功时才可用,我不知道如何将它传递给我的示波器幻灯片!!!!!!

我做错了什么?

在此先感谢

【问题讨论】:

    标签: angularjs http service


    【解决方案1】:

    bannerSlides() 不会立即返回您需要的值。它返回一个承诺,您可以在以后使用它来获取该值。

    在您的服务中,您可以使用$http() 产生的promise 的.then() 方法对结果进行初始处理:

     return $http({
        method: 'GET',
        dataType: "json",
        url: dataUrl
     }).then(function (data) {
         // inspect/modify the received data and pass it onward
         return data.data;
     }, function (error) {
         // inspect/modify the data and throw a new error or return data
         throw error;
     });
    

    然后您可以在控制器中执行此操作:

    app.controller('AppCtrl', function($scope, $http, agrService) {
         agrService.bannerSlides().then(function (data) {
             $scope.slides = data;
         });
    })
    

    【讨论】:

    • 非常感谢您的评论。我完全按照您的建议做了,但现在我的控制台中出现此错误:资源解释为图像,但使用 MIME 类型文本/html 传输:“localhost:8100”。
    • @Legues 嗯,我认为这可能无关紧要。我注意到我将您的“json”数据类型更改为“text”并忘记将其更改回来。你能把它改回“json”再试一次吗?
    • 我快到了。但是json中的数据条目是空的,我想它应该有数据存在于我的dataUrl中。我的数据 Json 具有以下值: [ { "id": 1, "url": "amendoeiraresort.com/assets/mobile/images/…" }, { "id": 2, "url": "amendoeiraresort.com/assets/mobile/images/…" }, { "id": 3、“网址”:“amendoeiraresort.com/assets/mobile/images/…”}]
    • 在我的控制器中,我可以这样做来输入数据: agrService.bannerSlides().then(function(data) { $scope.slides = data.data; }, function() {警报(“错误”);});
    • @Legues 我明白了。或者,您可以在您的服务中使用then() 回调执行return data.data;
    【解决方案2】:

    在您的服务中使用它

    .... 
    this.bannerSlides = function(){
         var dataUrl = "data/banner-rotator.json";
         return $http({
            method: 'GET',
            dataType: "json",
            url: dataUrl
        });
    };  
    ...
    

    这在你的控制器中

    agrService.bannerSlides().then(function(data) {
        $scope.slides = data;
    }, function() {
       //error
    });
    

    你不需要 $q 服务内的承诺,因为 $http 默认返回一个承诺

    $http 服务是一个函数,它接受一个参数——一个配置对象——即
    用于生成 HTTP 请求并返回带有两个 $http 特定方法的承诺:成功和错误

    reference

    这是Fiddle Demo

    【讨论】:

      【解决方案3】:

      您需要返回一个承诺并在回调中更新您的范围:

      app.service('agrService', function ($q, $http) {
      
       this.bannerSlides = function(){
          var ret = $q.defer();
          var dataUrl = "data/banner-rotator.json";
      
          // Simple GET request example :
          $http({
              method: 'GET',
              dataType: "json",
              url: dataUrl
          })
          .success( function(data, status, headers, config) {
      
              // this callback will be called asynchronously
              // when the response is available
      
              ret.resolve(data);
      
          }).error( function(data, status, headers, config) {
      
              // called asynchronously if an error occurs
              // or server returns response with an error status.
              ret.reject("Niente, Nada, Caput");
          });
          return ret.promise;
      
       }
      })
      
      app.controller('AppCtrl', function($scope, $http, agrService) {
       $scope.slides = null;
      
       agrService.bannerSlides().then(function(data){
         $scope.slides = data;
       }, function(error){
         // do something else
       });
      
      })
      

      【讨论】:

      • 您的bannerSlides 方法有一个无法访问的return 语句。而且您根本不需要 ret 变量。
      • 这取决于你想在哪里格式化你的答案,我删除了 leftoverreturn $http 谢谢。
      • 我不确定你的意思,但是不,ret 在这里完全没有必要,因为你已经有了一个承诺。 $q.defer() 是一种在您还没有承诺时创建承诺的机制。
      • 您可以很好地在服务中而不是在控制器中格式化您的答案。例如,这里我们只用数据来解析,而不是其余的参数。
      • 您仍然不需要ret 来格式化服务中的答案。
      【解决方案4】:

      您不能从异步调用中返回常规变量,因为在执行此成功块时,函数已经完成了它的迭代。 您需要返回一个 Promise 对象(作为指导方针,并且最好从服务中执行)。

      按照 $q$http 的 angular 文档,您可以自己构建一个用于异步调用处理的模板。

      模板应该是这样的:

      angular.module('mymodule').factory('MyAsyncService', function($q, http) {
      
      var service = {
          getData: function() {
              var params ={};
              var deferObject = $q.defer();
              params.nameId = 1;
              $http.get('/data', params).success(function(data) {
                  deferObject.resolve(data)
              }).error(function(error) {
                  deferObject.reject(error)
              });
      
              return $q.promise;
          }
      }
      });
      
      angular.module('mymodule').controller('MyGettingNameCtrl', ['$scope', 'MyAsyncService', function ($scope, MyAsyncService) {
      
          $scope.getData= function() {
              MyAsyncService.getData().then(function(data) {
                  //do something with data
              }, function(error) {
                  //Error 
              })
          }
      }]);
      

      【讨论】:

      • getData 方法的代码量大约是它需要的两倍(还有一个错误)。您正在使用一种非常迂回的方法来实现相当于只返回$http.get('/data', params)
      • 这是因为你不想在你的控制器中处理你的 http 结果,你只想在 100% 确定它有效时解析你的结果。
      • 我同意这一点,但那不是您在示例中显示的内容。您只是传递 dataerror 而不检查它们(并使用不必要的延迟对象来执行此操作)。
      猜你喜欢
      • 1970-01-01
      • 2013-07-31
      • 2018-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-21
      • 2012-12-30
      • 1970-01-01
      相关资源
      最近更新 更多