javascript - 单击任何按钮都会触发我的 UserService.getUsers 函数,但这不应该发生

标签 javascript angularjs

因此,我编写了一个服务,将我的 http 请求添加到其中并获取服务。在我的所有项目中,我都使用弹出框(md-dialog -> Angular Material )。现在我面临2个问题。第一个是,在添加用户后,我将检索所有用户,因此我的用户列表将显示双倍。第二个问题是,当应用程序加载时,会正确显示用户列表,但是当单击触发弹出窗口的任何按钮时,用户列表将增加一倍。

我想知道为什么会发生这种情况以及如何解决它。

这是我的应用程序的视觉效果 -> https://gyazo.com/ad135d42731d5cdc7be9d3b85aa57dc8

我的 app.js 代码的一部分:

zazzleApp.factory('UserService', function ($http) {
        var UserService = {};

        UserService.userList = []//this is the array of users that we use in the controller (and in the page)
        //whatever resides in this array will be shown on the page (because the controller is bound to it)

        //get the users from the API
        UserService.getUsers = function () {
        $http.get("api/users") //your API url goes here
            .success(function(dataFromServer){
                console.log('LOGGING DATADROMSERVER ', dataFromServer);

                dataFromServer.forEach(function(user, index, arr) { 
                    UserService.userList.push(user); 
                })


                //here you should update the usersList from the server like this:
                UserService.usersList = dataFromServer;
                return dataFromServer;
            })
            .error(function(errorFromServer){
            //something went wrong, process the error here
                console.log("Error in getting the users from the server");
            })
        };

        UserService.addUser = function (pUser) {
        //here you should do the $http.post and write some code on the .success() event. 
        //Just for an example I used here the .get() method to show you how to process the request, you should replace it
        //note the return $http.post below which takes our promise further to the controller so we can use it there if we want:
            return  $http.post('api/users/invite', {
                    'email': pUser.email,
                    'role_id': pUser.role
                }, {
                    headers: {
                        "Content-Type": "text/plain"
                    }
                })
            .success(function (data, status, headers, config) {
                //code to run if all went well:
                console.log("Service: the user has been added", data);
                //add the new user to the list. 
                //actually, you may want to call UserService.getUsers() here to get an updated list of users: all of them will automagically reflect in the page without refresh:
                UserService.usersList.push(pUser);

            })
            .error(function (data, status, headers, config) {//we had an error
                console.log("Failed to add user to DB");
            });
        };

        return UserService;
    })

//START CONTROLLER
angular.module('zazzleToolPlannerApp')
    .controller('CalendarCtrl', function ($scope, $mdDialog, $http, $rootScope, $timeout, User, Auth, UserService) {

        $scope.newUser = {};//this is the new user object. You can initialise it however you want
        $scope.newUser.email = "";//initialize the data for the new user
        $scope.newUser.role = "";

        //this is how you bind the list to the data in the service:
        $scope.users = UserService.userList;

        $scope.isAdmin = Auth.isAdmin;
        $scope.getCurrentUser = Auth.getCurrentUser;

        //ask the service to grab the data from the server. This is bound to the first button in the page
        $scope.getDataFromService = function () {
            UserService.getUsers(); //after this gets called, the data will be shown in the page automatically
        }
        $scope.getDataFromService();

        //ask the service to add a new user with the API (called from the second button):
        $scope.addUserWithService = function () {
            //note that you can process the promise right here (because of the return $http in the service)
            UserService.addUser($scope.newUser)
                .success(function(data){
                    //here you can process the data or format it or do whatever you want with it
                    console.log("Controller: the user has been added");
                    $scope.users = [];// EMPTY THE ARRAY
                    UserService.getUsers();

                })
                .error(function(data){
                    //something went wrong
                    console.log("Controller: the user has been added");
                });         
        }
   });

最佳答案

在您的服务中将功能更改为:

UserService.getUsers = function () {
  $http.get("api/users")
  .success(function(users) {
    console.log('LOGGING DATADROMSERVER ', users);
    return UserService.usersList = users;
  })
  .error(function(err) {
    console.log("GET usres error: ", err);
  });
};

无需在那里运行 forEach 并按用户添加用户。只需将其分配给来自服务器的响应即可。

在你的 Controller 中:

  $scope.addUser = function () {
    UserService.addUser($scope.newUser)
    .success(function(newUser){
      console.log("Controller: user has been added: ", newUser);
    })
    .error(function(err){
      console.log("Controller: Add user error: ", err);
    });         
  }

无需清空数组并再次获取用户,因为服务正在处理 Controller 的数据。

除此之外,这里对您的代码进行了一些重构,以使其更具可读性和可维护性:

angular.module('zazzleToolPlannerApp')
.factory('UserService', UserService)
.controller('CalendarCtrl', CalendarCtrl);

function UserService($http) {
  var service = {
    getUsers: getUsers,
    add: add,
    userList: []
  };

  return service;

  function getUsers() {
    $http.get("api/users").then(success, error);

    function success(users) {
      console.log('LOGGING DATADROMSERVER ', users);
      return service.usersList = users;
    }

    function error(err) {
      console.log("GET usres error: ", err);
    }
  }

  function add(user) {
    var data = {
      email: user.email,
      role_id: user.role
    };

    return  $http.post('api/users/invite', data, { 
        headers: { "Content-Type": "text/plain" }
      }).then(success, error);

    function success(data, status, headers, config) {
      console.log("Service: the user has been added", data);
      service.usersList.push(user);
    }

    function error(data, status, headers, config) {
      console.log("Failed to add user to DB");
    }
  };

  return service;
}



function CalendarCtrl($scope, $mdDialog, $http, $rootScope, $timeout, User, Auth, UserService) {
  angular.extend($scope, {
    getCurrentUser: Auth.getCurrentUser,
    getUsers: UserService.getUsers,
    isAdmin: Auth.isAdmin,
    addUser: addUser,
    users: UserService.userList,
    newUser: {}
  });

  init();

  function init() {
    $scope.getUsers();
    initNewUser();
  }

  function initNewUser() {
    $scope.newUser = { email: "", role: "" };
  }

  function addUser() {
    UserService.addUser($scope.newUser)
    .success(function(newUser){
      console.log("Controller: user has been added: ", newUser);
    })
    .error(function(err){
      console.log("Controller: Add user error: ", err);
    })
    .finally(function() {
      initNewUser();
    });
  }
}

此外,您最好使用controllerAs语法来避免作用域冲突。

所以你的 Controller 将是:

function CalendarCtrl($mdDialog, $http, $rootScope, $timeout, User, Auth, UserService) {
  var ctrl = this;

  angular.extend(ctrl, {
    getCurrentUser: Auth.getCurrentUser,
    getUsers: UserService.getUsers,
    isAdmin: Auth.isAdmin,
    addUser: addUser,
    users: UserService.userList,
    newUser: {}
  });

  init();

  function init() {
    ctrl.getUsers();
    initNewUser();
  }

  function initNewUser() {
    ctrl.newUser = { email: "", role: "" };
  }

  function addUser() {
    UserService.addUser(ctrl.newUser)
    .success(function(newUser){
      console.log("Controller: user has been added: ", newUser);
    })
    .error(function(err){
      console.log("Controller: Add user error: ", err);
    })
    .finally(function() {
      initNewUser();
    });
  }
}

请告诉我这是否有效以及您是否有疑问:)

关于javascript - 单击任何按钮都会触发我的 UserService.getUsers 函数,但这不应该发生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31874167/

相关文章:

javascript - 使用 JavaScript 将文本从一个页面传递到下一个页面

javascript - 文本的实时预览使链接在悬停时不会改变背景颜色

javascript - 构建 Promise 对象的有效方法

javascript - 如何在 AngularJS 中选择多个默认选项?

angularjs - 如何以 Angular 访问弹出模型 Controller 中的 ng-model 值?

angularjs - 解析 Angular 2 中的错误主体

Rails 3.1 中的 JavaScript 单元测试

javascript - SteemJS 无法在 Firefox/IE 中运行

javascript - 使用 angularjs 根据时间更改背景颜色。

javascript - 使用 AngularJS 对 Json 中的 2 个值求平均值