【问题标题】:how to call a function in the controller from service in angular application如何从角度应用程序中的服务调用控制器中的函数
【发布时间】:2016-06-29 18:44:37
【问题描述】:

我有一个带有控制器和服务的 Angular 应用程序。我从控制器调用服务,服务进行后端调用,应该调用控制器中的另一个函数。我能够从控制器调用服务,但无法调用控制器中的函数。

这里是代码。控制器:

(function(){
  angular.module("addressModule")

    // The controller for the standardized Address
    .controller('myController', ['$resource','myService', myControllerFunction]);

    myControllerFunction.$inject = ['addressConfig', 'myService', '$resource'];

    function myControllerFunction (addressConfig, myService, $resource, $scope) {
      var vm = this;

      // cannot show what the model is
      vm.model = "some model";
      myService.callGISFromService(vm.model);

      this.callFunctionInController = function(){
        console.log("The controller function is called");
      }
    }
})();

服务的代码是

(function(){

    angular.module('addressModule')
        .service('myService', ['$resource',  myServiceFunction]);

    myServiceFunction.$inject = ['$resource'];

    function myServiceFunction ($resource) {

        this.callGISFromService = function (model) {
            var urlForTheGISCall = "some URL";
            var resource = $resource(urlForTheGISCall);
            console.log("control is in the service");

            resource.get().$promise
            .then(function successCallback(response) {

                this.callFunctionInController();

            }), function errorCallback(response) {
                console.log("the backend call did not work");

            }
        };
    }
})();

我能够进行后端调用并获取所需的数据,但无法调用控制器中的函数。

控制台报错:

TypeError: this.callFunctionInController is not a function

【问题讨论】:

  • $inject 数组不是必须与控制器中的参数顺序相同吗?你把顺序搞混了。
  • 你也注入了两次,一次使用括号语法,一次使用 $inject
  • @Daniel_L 我已经更改了订单,但没有任何区别。
  • @koox00 如果我不注入两次,应用程序将无法正常工作。
  • 删除控制器中的数组表示法,只用注入服务注入,也注入 $scope 并注意顺序。如果您不使用缩小,应用程序即使完全没有注入也应该可以运行。

标签: javascript angularjs


【解决方案1】:

您可能想看看this post,它解释了如何使用$broadcast,在服务-控制器之间建立通信。

您还可以将服务中的函数转换为异步函数,以便控制器知道函数何时成功完成或出现错误。它看起来像这样:

(function(){

angular.module('addressModule')

.service('myService', ['$resource', '$q',  myServiceFunction]);

        myServiceFunction.$inject = ['$resource', '$q'];

        function myServiceFunction ($resource) {

        this.callGISFromService = function (model) {

            var deferred = $q.defer();

            var urlForTheGISCall = "some URL";

            var resource = $resource(urlForTheGISCall);
            console.log("control is in the service");

            resource.get().$promise
            .then(function successCallback(response) {

                deferred.resolve('success');

            }), function errorCallback(response) {
                deferred.reject('error');
            }

              return deferred.promise;
        };
    }
})();

这使得你可以像这样在控制器中调用你的函数:

(function(){
    angular.module("addressModule")
    // The controller for the standardized Address

        .controller('myController', ['$resource','myService', myControllerFunction]);

        myControllerFunction.$inject = ['addressConfig', 'myService', '$resource'];

        function myControllerFunction (addressConfig, myService, $resource, $scope) {

            var vm = this;
            // cannot show what the model is
            vm.model = "some model";
            myService.callGISFromService(vm.model).then(function(success){
                function(){
                    console.log("The controller function is called");
            }
            });

}
})();

我个人会选择第二个选项,因为它比使用广播更优雅和轻量级。在您的应用程序中分配广播可能会使它变得非常混乱且难以阅读。 For more info 关于异步函数,查看 angularjs 文档

【讨论】:

  • 使用事件在类之间进行通信是一种不好的做法。有更好的模式,例如观察者、访问者和策略模式。
  • 什么是 $q,我是否必须创建任何依赖项或注入任何东西才能使用它。我收到一个错误:ReferenceError: $q is not defined
  • 不,它不需要任何特定的依赖项,请查看文档,它已得到很好的解释。如果此错误仍然存​​在,请在此处发布,以便我们一起查看。
【解决方案2】:

这是 JavaScript 回调模式。您还可以使用观察者模式。

我们可以使用subscribe 方法创建一个 Observable 服务。此方法将接受来自订阅控制器的function

Observable.$inject = ['$http'];
function Observable($http) {
    this.$http = $http;
    this.subscribers = [];
}

Observable.prototype.subscribe = function(fn) {
    this.subscribers.push(fn);
}

Observable.prototype.getSomething = function() {

    var self = this;
    this.$http.get('/something').then(function() {
        self.subscribers.forEach(function(fn) { fn() })));
}

app.service('observable', Observable);

然后您可以在控制器中订阅更新:

ObserverController = ['observale'];
function ObserverController(observable) {
    observable.subscribe(this.callback);
}

ObserverController.prototype.callback = function() {
    // this is called from the Observable service
}

app.controller('ObserverController', ObserverController);

在您的控制器中,您明确订阅从 Observable 服务获取更新。每次调用服务中的getSomething方法时,都会调用之前传递给subscribe方法的函数。

通常,Observable 会将对象/值传递给 Observer。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-22
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多