javascript - event.preventDefault() 不等待 promise 解决

标签 javascript angularjs express angular-ui-router

我正在使用 event.preventDefault() 技术根据我从后端获取的标志值有条件地将用户重定向到适当的状态。一切似乎都工作正常,除了有时渲染实际页面然后发生重定向,而且在极少数情况下也是如此。实际页面的渲染持续时间也很短。以下是我正在使用的代码片段:

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){

  if (fromState.name === '' && toState.name === "myState"){

    Auth.isLoggedInAsync(function(loggedIn) {
      if (!loggedIn) {
        event.preventDefault();
        $state.go('state1');
      } else {
          event.preventDefault();
          Auth.getNextStateForUser()
          .then(function(data) {
            console.log(data.nextState);
            $state.go(data.nextState);
          })
          .catch(function(err){
              console.log(err);
              $state.go(toState.name);
          });
      }
    });

我遵循的逻辑是,检查用户是否登录,然后重定向到 state1,否则根据从后端获取的 nextstateValue 重定向到下一个适当的状态。如果发生错误,则打开实际页面,不进行任何重定向。

我希望我能清楚地表达自己在做什么。只是想知道我面临的问题是否是真正的问题,或者我的做法有误。

我也将其发布在 github 页面上,但似乎我是唯一面临此问题的人。

请检查此以获取更多信息: https://github.com/angular-ui/ui-router/issues/2088

谢谢

编辑:根据答案,我更新了使用 ui-router 解析的代码,并将 isLoggedInAsyc 转换为返回 promise 。

resolve: {

  promiseState: function(Auth, $state, $q, $stateParams) {

    var deferred = $q.defer();

    Auth.isLoggedInSync()
    .then(function(isLoggedIn){
        console.log(isLoggedIn);
        if(isLoggedIn) {
          Auth.getNextStateForUser()
              .then(function(data) {
                console.log(data.nextState);
                $state.go(data.nextState);
                deferred.resolve(data);
               })
              .catch(function(error) {
                console.log(error);
                deferred.reject(error);
          }); 
        }

        deferred.resolve(isLoggedIn);
    })
    .catch(function(err){
        console.log(err);
        deferred.reject(err);
    });

    return deferred.promise;
  }
}

我的 isLoggedIn() 返回 promise 。

  isLoggedInSync: function(callback) {
    var cb = callback || angular.noop;
    var deferred = $q.defer();
    if(currentUser.hasOwnProperty('$promise')) {
      currentUser.$promise.then(function() {
        deferred.resolve(true);
        return cb(true);
      }).catch(function() {
        deferred.resolve(false);
        return cb(false);
      });
    } else if(currentUser.hasOwnProperty('role')) {
      deferred.resolve(true);
    } else {
      deferred.resolve(false);
    }
    return deferred.promise;
  }

最佳答案

正如 @milaenlempera 提到的,所有 Angular 事件都是同步的,在这种情况下没有真正的方法可以很好地处理异步。我们的生产代码中遇到了这个问题,我们的解决方案是使用 ui-router 中的 resolve 功能。这就是我们解决它的方法(显然插入到您的代码中)

.state({
  name: 'myState',
  resolve: {
    principal: ['Auth', '$state', '$q', function(Auth, $state, $q) {
      var deferred = $q.defer();
      Auth.isLoggedInAsync(function(loggedIn) {
        if(!isLoggedIn) {
          deferred.resolve($state.go('state1'));
          return;
        }
        return Auth.getNextStateForUser()
          .then(function(data) {
            $state.go(data.nextState);
           })
          .catch(function(error) {
            deferred.reject(error);
          });
      });
      return deferred.promise;
    }]
  }
});

我建议使用 Auth.isLoggedInAsync 返回一个 promise 。

此外,如果 Auth.getNextStateForUser() 被拒绝,您的原始代码将导致无限循环。它将尝试转到名为 toState.name 的状态,这是刚刚导致错误的状态,这将导致另一个错误并导致它转到 toState.name....

由于resolve级联,如果您想共享权限规则,则可以实现子状态。确实很糟糕,没有办法只在状态上放置一个属性并在其他地方处理异步权限检查,但这就是我们目前遇到的情况。

根据评论,这是一个使用修改后的代码进行 promise 链接的示例。

  promiseState: ['Auth', '$state', function(Auth, $state) {
    return Auth.isLoggedInSync()
      .then(function(isLoggedIn) {
        if(isLoggedIn) {
          return Auth.getNextStateForUser().then(function(data) {
            return data.nextState;
          });
        }
        // If the user isn't logged in, return the state that you should go to instead
        return 'state1';
      })
      .then(function(nextState) {
        return $state.go(nextState);
      });
  }]

关于javascript - event.preventDefault() 不等待 promise 解决,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31368338/

相关文章:

node.js - express multer上传的文件url

javascript - 在 Express + Node.js 中处理发布的数据?

javascript - 如何找到数组中第二好的?

javascript - 如何通过 Jasmine spy 将被拒绝/失败的 promise 返回到单元测试中的 Angular Controller

angularjs - 2.0.0 版本无法绑定(bind)到 'ngIf',因为它不是 'div' 的已知属性

javascript - 使用 Node CRON作业调用自己的请求

javascript - 默认调用函数?

php - header 中的 Javascript 问题

javascript - 隐藏手机面包屑导航中的最后一个文本 block - Prestashop

angularjs - 用于ElasticSearch的Nginx反向代理仅允许_search端点