【问题标题】:How to update $rootScope in Angular 1 inside an async callback?如何在异步回调中更新 Angular 1 中的 $rootScope?
【发布时间】:2017-12-31 21:35:28
【问题描述】:

我确定这是一个非常常见的问题,但由于某种原因我找不到有效的解决方案。

我有一个非常简单的 Firebase 实时数据库和 Angular 1 设置。我的 html 中有这个指令

<div id="usersListWrapper" ng-controller="UsersListController" ng-init="loadUsersList()">

然后在我的 loadUsersList() 方法中,我调用 Firebase 数据库来获取数据

$rootScope.users = [];

var usersRef = firebase.database().ref('/users');
usersRef.on('value', function(snapshot) {
    console.log("loaded users list");
    var users = snapshot.val();
    updateUsersTable(users);
});

最后,在updateUsersTable(users) 内部,我更新了我的$rootScope.users 变量

var updateUsersTable = function(users) {
    $.each(users, function(key, value) {
        var user = {
            username: key,
            ...
        }

        $rootScope.users.push(user);
    }
}

但是,即使$rootScope.users 变量正确更新(我使用 Chrome 中的 devtools 进行了验证),html 也不会更新:/

如果这是一个重复的问题,请提前道歉。帮助将不胜感激。

【问题讨论】:

  • 听起来你需要运行一个摘要循环。 $scope.$apply(function() { $rootScope.users.push(user);});
  • @LT56 根据我的阅读,手动调用$apply 是不好的。但是,我也尝试过,每当我在列表中添加一些东西时都会引起问题。我一直得到这个:Error: $apply already in progress
  • 我会将 scope.$apply 放在事件监听器上 b/c AngularJS 不知道事件何时被触发,因为它没有管理它。即: usersRef.on('value', scope.$apply(function () { });

标签: html angularjs firebase firebase-realtime-database


【解决方案1】:

$rootScope 不是存储用户对象的合适位置。一般来说,修改 $rootScope 应该被认为是在没有其他选择的情况下做的事情。

您应该做的是创建一个 userService 并将其注入到您需要访问用户数据的任何位置。

同样的建议也适用于使用 ng-init。我猜你刚刚开始使用 Angularjs。我强烈建议您熟悉 John Papa 的 Angularjs 样式指南:https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md。它有点过时了,因为它没有涵盖所有内容的组件,但是遵循样式指南可以非常容易地迁移到组件。

【讨论】:

    【解决方案2】:

    这里的解决方案似乎有效:Firebase callbacks and AngularJS

    有点老套,但我猜它有效。谢谢那些回答的人。

    【讨论】:

      【解决方案3】:

      正如我在上面的评论中提到的,我会将 scope.$apply 放在事件侦听器上 b/c AngularJS 不知道事件何时被触发,因为它没有管理它。即:

       usersRef.on('value', scope.$apply(function () { 
          console.log("loaded users list");
          var users = snapshot.val();
          updateUsersTable(users);
       }));
      

      或者您可以查看 $evalAsync。来自 AngularJS 文档:

      $evalAsync([表达式], [locals]);执行表达式 以后的当前范围。

      $evalAsync 不保证表达式何时 执行,仅此:

      它将在安排评估的函数之后执行 (最好在 DOM 渲染之前)。至少一个 $digest 循环将是 在表达式执行后执行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 2021-07-22
        • 1970-01-01
        • 2014-12-23
        相关资源
        最近更新 更多