AngularJS $state.go 在前一个语句执行完成之前执行

AngularJS $state.go executes before previous statement execution completes

我正在为 RESTful 网络服务使用 AngularJS、ui-路由器和 $resource。

单击 html 视图中的按钮,调用以下函数,即 $scope.login()。因此,REST 服务(通过 $resource)被调用并且 returns 一个用户,以防 user/pass 是正确的,

$scope.login = function() {
myfactory.get({
        email: $scope.user.email,
        password: $scope.user.password
    },function(user) {
        accessmgr.grantAccess(user);      //Line of interest - loi1
        $state.go('app.dashboard-v1');    //Line of interest2 - loi2
    }, function(x) {
        if (x.status == 401)
            $scope.authError = 'Email or Password not right';
        else
            $scope.authError = 'Server Error! Are you connected to internet?';
    });
}

如果上述成功执行,将调用另一个工厂函数(上面的 loi1)将用户实例存储在 $localStorage 中,如下所示;

myapp.factory('accessmgr', function($localStorage) {
    //var User = {};
    return {grantAccess: function(usr) {
            $localStorage.user = usr;
        }
    }});

和 ui-router $scope.go(...) 将用户带到仪表板。

问题: 有时 $state.go(...) 在 accessmgr.grantAccess(...) 之前执行导致异常,因为新状态从尚未写入的 $localStorage 读取用户.手动重新加载页面解决了问题。

任何帮助将不胜感激。

localStorage 本身以同步方式工作,但 ngStorage 的 $localstorage 不是。后者旨在与范围和 is tied to Angular digest cycles 结合使用。我的猜测是

myapp.factory('accessmgr', function($localStorage) {
    return {grantAccess: function(usr) {
            $localStorage.user = usr;
            $localStorage.$apply();
        }
    }});

可能会有帮助。 ngStorage 在这样使用时并没有真正发挥作用,可能像 store.js 这样的 JS 通用库应用得更好。

一个好的替代方法是使用充当单一事实来源的模型,并将数据转储到引擎盖下的 localStorage。根据项目的规模,js-data-angular 可以认为是一个可靠的解决方案。

ngStorage 的 $localStorage 不能在不使用 watchers 的情况下直接引用(根据 here, alternatively it can to be passed as a reference to hook to $scope as mentioned as recommended approach here.

不推荐)

对我来说,我通过工厂使用 $localStorage 并将其绑定到 rootScope,如下所示;

$rootScope.$storage = $localStorage;

因此

myapp.factory('accessmgr', function($localStorage) {
  $rootScope.$storage = $localStorage;
  return {
    grantAccess: function(usr) {
        $rootScope.$storage.user = usr;
      },
    getUser: function() {
        return $rootScope.$storage.user;
      }
  }});