当前位置: 首页 > 面试题库 >

将$ scope注入角度服务函数()

淳于禄
2023-03-14
问题内容

我有服务:

angular.module('cfd')
  .service('StudentService', [ '$http',
    function ($http) {
    // get some data via the $http
    var path = 'data/people/students.json';
    var students = $http.get(path).then(function (resp) {
      return resp.data;
    });     
    //save method create a new student if not already exists
    //else update the existing object
    this.save = function (student) {
      if (student.id == null) {
        //if this is new student, add it in students array
        $scope.students.push(student);
      } else {
        //for existing student, find this student using id
        //and update it.
        for (i in students) {
          if (students[i].id == student.id) {
            students[i] = student;
          }
        }
      }
    };

但是当我打电话时save(),我无法访问$scope和获得ReferenceError: $scope is not defined。因此,对我而言,逻辑上的步骤是为save()提供$scope,因此我还必须将其提供/注入到service。因此,如果我这样做:

  .service('StudentService', [ '$http', '$scope',
                      function ($http, $scope) {

我收到以下错误:

错误:[$ injector:unpr]未知提供程序:$ scopeProvider <-$ scope <-StudentService

错误中的链接(哇,很干净!)让我知道它与注入器相关,并且可能与js文件的声明顺序有关。我曾尝试在中对它们进行重新排序index.html,但是我认为这更简单一些,例如我注入它们的方式。

使用Angular-UI和Angular-UI-Router


问题答案:

$scope你看到被注入控制器是不是有些服务(如的注射材料的其余部分),而是一个范围对象。可以创建许多作用域对象(通常是从父作用域继承的原型)。所有作用域的根都是$rootScope,您可以使用$new()任何作用域(包括$rootScope)的方法来创建新的子作用域。

范围的目的是将应用程序的演示文稿和业务逻辑“粘合在一起”。将a传递$scope给服务没有多大意义。

服务是用于(例如)共享数据(例如,在多个控制器之间)的单例对象,通常封装可重用的代码段(因为它们可以被注入并在需要它们的应用程序的任何部分中提供其“服务”:控制器,指令过滤器,其他服务等)。

我敢肯定,各种方法都可以为您服务。一个是这样的:
由于StudentService负责处理学生数据,因此您可以StudentService保留一组学生,并使其与可能感兴趣的任何人(例如您的$scope)“共享”它。如果还有其他需要访问该信息的视图/控制器/过滤器/服务(如果现在没有任何视图,请很快就弹出它们也不要感到惊讶),这将变得更加有意义。
每次添加新学生(使用该服务的save()方法)时,该服务自己的学生数组将被更新,并且共享该数组的所有其他对象也将被自动更新。

基于上述方法,您的代码可能如下所示:

angular.
  module('cfd', []).

  factory('StudentService', ['$http', '$q', function ($http, $q) {
    var path = 'data/people/students.json';
    var students = [];

    // In the real app, instead of just updating the students array
    // (which will be probably already done from the controller)
    // this method should send the student data to the server and
    // wait for a response.
    // This method returns a promise to emulate what would happen 
    // when actually communicating with the server.
    var save = function (student) {
      if (student.id === null) {
        students.push(student);
      } else {
        for (var i = 0; i < students.length; i++) {
          if (students[i].id === student.id) {
            students[i] = student;
            break;
          }
        }
      }

      return $q.resolve(student);
    };

    // Populate the students array with students from the server.
    $http.get(path).then(function (response) {
      response.data.forEach(function (student) {
        students.push(student);
      });
    });

    return {
      students: students,
      save: save
    };     
  }]).

  controller('someCtrl', ['$scope', 'StudentService', 
    function ($scope, StudentService) {
      $scope.students = StudentService.students;
      $scope.saveStudent = function (student) {
        // Do some $scope-specific stuff...

        // Do the actual saving using the StudentService.
        // Once the operation is completed, the $scope's `students`
        // array will be automatically updated, since it references
        // the StudentService's `students` array.
        StudentService.save(student).then(function () {
          // Do some more $scope-specific stuff, 
          // e.g. show a notification.
        }, function (err) {
          // Handle the error.
        });
      };
    }
]);

使用此方法时应注意的一件事是永远不要重新分配服务的数组,因为那样的话,其他任何组件(例如,作用域)仍将引用原始数组,并且您的应用程序将中断。
例如清除数组StudentService

/* DON'T DO THAT   */  
var clear = function () { students = []; }

/* DO THIS INSTEAD */  
var clear = function () { students.splice(0, students.length); }

另请参 见此简短演示

小更新:

要避免在谈论使用服务而不是通过service()功能创建服务时可能引起的混乱,请多说几句。

引用以下 文档$provide

Angular 服务 是由 服务工厂 创建的单例对象。这些 服务工厂 是由 服务提供商 创建的功能。该
服务提供商 是构造函数。实例化后,它们必须包含一个名为的属性$get,该属性包含 服务工厂 功能。
[…]
…的$provide服务有额外的辅助方法,而不指定提供商注册服务:

  • provider(provider) -向$ injector注册服务提供商
  • constant(obj) -注册可以由提供者和服务访问的值/对象。
  • value(obj) -注册只能由服务而非提供者访问的值/对象。
  • factory(fn) -注册服务工厂函数fn,该函数将包装在服务提供程序对象中,该对象的$ get属性将包含给定的工厂函数。
  • service(class) -注册一个构造函数,将包装在服务提供者对象中的类,该类的$
    get属性将使用给定的构造函数实例化一个新对象。

基本上,它说的是每个Angular服务都是使用来注册的$provide.provider(),但是对于更简单的服务,有“捷径”方法(其中两个是service()factory())。
所有这些都“归结为”服务,因此使用哪种方法并没有多大区别(只要该方法可以满足服务要求)。

顺便说一句,providervs vs servicevs
factory是Angular新手最困惑的概念之一,但是幸运的是,有很多资源(在SO上)使事情变得更容易。(只需四处搜索。)

(我希望这可以解决-如果不能,请告诉我。)



 类似资料:
  • 问题内容: 我已经看到angular.factory()和angular.service()都用于声明服务;但是,我在官方文档中找不到 任何地方。 两种方法有什么区别? 应该使用哪个(假设他们做不同的事情)? 问题答案: 直到我以这种方式对自己说: 服务 :您编写的 函数 将是 新的 -ed: Factory* :将 调用 您编写的 函数 (构造函数): * 您可以根据自己的意愿进行操作,但是有一

  • 问题内容: 我写了一个AngularJS服务,我想对其进行单元测试。 我的app.js文件已注册: 我可以测试DI是否像这样工作: 这证明了可以通过DI框架创建服务,但是接下来我要对服务进行单元测试,这意味着要模拟注入的对象。 我该怎么做呢? 我试过将我的模拟对象放在模块中,例如 并将服务定义重写为: 但是后者似乎停止了DI所创建的所有服务。 有人知道我可以如何为单元测试模拟注入的服务吗? 谢谢

  • 问题内容: 我定义了一个范围变量。加载视图时,我从数据库加载字符串并将其设置为。然后,我在正在使用的texteditor(Froala)上进行填充。 下面是该视图的代码: 所以基本上我将texteditor 设置为ng- model。因此,当我对文本编辑器进行更改时,它会修改值。 我发现这很奇怪的一件事是,当我在texteditor中修改文本时,它在div内发生了变化。但是,它不会在div之外更新

  • 问题内容: 是否可以在angularJS中将一个服务注入到另一个服务中? 问题答案: 是。遵循angularjs中的常规注入规则。 感谢@simon。最好使用数组注入以避免最小化问题。

  • 问题内容: 我在Groovy中实现了Grails服务,我想在Web应用程序中将其注入Java类。我知道我可以通过applicationContext.getBean(“ exampleService”)获得Java中的bean,但是在编译时类型ExampleService是未知的。 我可以简单地导入服务吗?它似乎没有声明一个典型的包。 (我对Grails和Java Web还是很陌生,因此非常感谢能

  • 我有一些UserService对用户实体进行操作。我创建了自己的注释和ConstraintValidator类作为实现 我需要将UserService注入到ConstraintValidator中。而且,正如spring文档所说,在注册bean之后: 不幸的是,它对我没有作用。我在字段(在实现ConstraintValidator的类内)使用NullPointerException累加stackt