【问题标题】:Using Angular $http in a service to fire on ng-click在服务中使用 Angular $http 触发 ng-click
【发布时间】:2016-03-24 03:16:11
【问题描述】:

我目前正在使用 Angular 1.3.14,我想在单击链接时使用 $http 发出请求。我试图将 $http 请求放在服务中,这样它就不会绑定到任何一个控制器,并且可以被多个控制器访问。我创建了两个函数 sayHello() 和 getData()。我希望每个都在单击时显示 console.log。只有 sayHello() 函数可以,getData() 函数不行。这是我不明白的。

  1. 为什么 $http 请求在加载时触发,而不是在点击时触发,而 sayHello 函数却完美运行?

  2. 如何修改我的代码以使其按预期工作?

    <p><a href="#" ng-click="getData()">Console Log Our Data</a></p>
    <p>
      <a href="#" ng-click="sayHello()">Console Log The Word "Hello"</a></p>
    

    var app = angular.module('myApp', [])
    
    .controller('mainCtrl', function($scope, dataService){
    
    $scope.sayHello = dataService.sayHello;
    
    $scope.getData = dataService.getData(function(response){
            $scope.myData = response.data;
        console.log($scope.myData);
        });
    })
    .service('dataService', function($http){
    
    this.getData = function(callback){
          $http.get('http://jsonplaceholder.typicode.com/posts')
            .then(callback);
        }
    
      this.sayHello = function(){
        console.log("Hello!");
      }
    
    
    });
    

Codepen 供参考http://codepen.io/benweiser/pen/remvvo/

【问题讨论】:

    标签: javascript angularjs http angularjs-scope


    【解决方案1】:

    那是因为$scope.getData应该是一个函数时等于undefined

    $scope.getData = function () {
      dataService.getData(function(response) {
         $scope.myData = response.data
         console.log($scope.myData)
      })
    }
    

    更新:您可以从方法调用或方法本身发送参数,假设您有以下输入

    <input ng-model="name">
    

    然后您可以使用发送值并在您的服务中使用它,如下所示

    <a ng-click="getData(name)">get data</a>
    
    $scope.getData = function (name) {
      dataService.getData(name)
         .then(function (response) { ... })
    }
    

    或者直接在控制器中使用

    <a ng-click="getData()">get data</a>
    
    $scope.getData = function () {
      dataService.getData($scope.name)
         .then(function (response) { ... })
    }
    

    请注意,两者都假设 dataService.getData() 返回一个承诺而不是传递回调,因此如果您想像上面那样编写它,您还需要在您的服务上执行以下操作

    this.getData = function (name) {
      // do something with name
      return $http.get('http://jsonplaceholder.typicode.com/posts/' + name)
    }
    

    您应该阅读更多关于 Promises 与回调以及如何利用它们的信息:)

    【讨论】:

    【解决方案2】:

    当你这样做时

    $scope.getData = dataService.getData(function(response){
        $scope.myData = response.data;
        console.log($scope.myData);
     });
    

    })

    dataService.getData 立即执行。结果,$scope.getData 被设置为一个承诺,而不是您打算绑定到 ng-click 的函数

    将此行 $scope.getData = dataService.getData 更改为以下内容,这实际上将设置一个带有回调到 $scope.getData 的函数

    $scope.getData = dataService.getData.bind(this, function(response) {
        $scope.myData = response.data;
        console.log($scope.myData);
    });
    

    【讨论】:

    • 与 Maurcio 的方法相比有什么优点或缺点吗?
    • this.getData 在 OP 示例中返回未定义,而不是承诺
    【解决方案3】:

    我会尝试做这样的事情。应该很容易应用到您上面的代码中

    //in your factory
    app.factory('dataFactory',function($http){
    
        factory = {};
    
        //get data
        factory.getData = function(obj){
            return $http({
                method: 'GET',
                url: 'http://jsonplaceholder.typicode.com/postsn'
            })
        };
    
        return factory
    }); 
    
    //in your controller
    app.controller(someCtrl,function($scope,dataFactory){
    
      dataFactory.getData().then(function(data){
          console.log('This will be your data: ', data)
      })
    
    })
    

    【讨论】:

    • 谢谢,我还不太了解我要做的工厂,我必须点击文档来了解它与服务。
    【解决方案4】:

    Ajax 查询是在控制器首次加载时进行的。您与“getData”的绑定不是使用函数,而是使用 ajax 调用,这就是它没有被触发的原因。

    此重构适用于 codepen:

    'use strict';
    
    var app = angular.module('myApp', [])
    
    .controller('mainCtrl', function($scope, dataService){
    
        $scope.sayHello = dataService.sayHello;
    
        $scope.getData = function(){
        dataService.getData().then(
            function(response){
                $scope.myData = response.data;
                    console.log($scope.myData);
                }
            );
        }
    })
    
    .service('dataService', function($http){
    
        this.getData = function(callback){
            return $http.get('http://jsonplaceholder.typicode.com/posts');
        }
    
        this.sayHello = function(){
            console.log("Hello!");
        }
    
    });
    

    主要更新:

    1. $scope.getData 绑定到函数,而不是 Ajax 调用/承诺
    2. 承诺不在服务范围内(欢迎提供更好的解决方案 :-))。
    3. dataService.getData 作为函数调用。 (没有以其他方式工作)。

    【讨论】:

      猜你喜欢
      • 2017-06-21
      • 2014-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-02
      • 2016-01-19
      • 2015-10-29
      • 1970-01-01
      相关资源
      最近更新 更多