【问题标题】:Wait for response in AngularJS $http等待 AngularJS $http 中的响应
【发布时间】:2016-05-26 09:44:17
【问题描述】:

好的,所以我很确定我已经多次找到答案 - 我只是不明白。

我正在构建一个单页应用程序,它在每个$routeChangeStart 上检查用户是否已登录。如果用户未登录,则重定向到登录页面。 我的问题是configService.isLoggedIn() 正在使用$http,这意味着它是异步的,其余代码不会等待它被解决。

所以简而言之,我需要先解决 isLoggedIn() 函数,然后再继续执行任何其他代码。

我在 $q.defer() 上看到了很多,但我无法理解它。

提前致谢。

app.service('configService', ['$http', '$q', '$location', '$rootScope', function ($http, $q, $location, $rootScope) {
    var self = this;

    this.isLoggedIn = function () {
        $http.get('/internalAPI.php?fn=login').then(function (result) {
            if (result.data.isLoggedIn === true) {
                $rootScope.isLoggedIn = true;
            }
            else {
                $rootScope.isLoggedIn = false;
            }
        }, function() {
            $rootScope.isLoggedIn = false;
        });
        return $rootScope.isLoggedIn;
    }
}]);

app.service('navigationService', ['$rootScope', '$location', '$timeout', 'configService', function ($rootScope, $location, $timeout, configService) {

    var self = this;

    $rootScope.$on('$routeChangeStart', function (event, next, current) {
        if (configService.isLoggedIn() !== true) {
            // no logged in user, redirect to /login
            if (next.templateUrl != "resources/views/login.php") {
                $location.path("/login");
                $rootScope.subTitle = 'Login';
            }
        //user is logged in but is trying to view the login page, redirect
        } else if (next.templateUrl == 'resources/views/login.php') {
            $location.path('/');
        }

【问题讨论】:

  • 为什么这么复杂?我们所做的以及我认为的标准是:让服务器在用户不再登录时返回状态码 401。然后我们在客户端(也在 angularjs 中)有一个拦截器,如果请求返回此状态代码,它将用户重定向到登录视图。
  • 同意雷内。与显式发送单独的 http 请求相比,这种处理身份验证的方式更为优雅。

标签: javascript angularjs promise deferred


【解决方案1】:

你可以从你的函数中返回 Promise 并对这个 Promise 对象进行操作。根据Angular $http documentation$http 对象基于promise mechanism

app.service('configService', ['$http', function ($http) {
    var self = this;

    this.isLoggedIn = function () {
        return $http.get('/internalAPI.php?fn=login');
    }
}]);

app.service('navigationService', ['$rootScope', '$location', '$timeout', 'configService', function ($rootScope, $location, $timeout, configService) {

    var self = this;

    $rootScope.$on('$routeChangeStart', function (event, next, current) {
        configService.isLoggedIn().then(function(result) {
            if (result !== true) {
                // no logged in user, redirect to /login
                if (next.templateUrl != "resources/views/login.php") {
                    $location.path("/login");
                    $rootScope.subTitle = 'Login';
                }
            //user is logged in but is trying to view the login page, redirect
            } else if (next.templateUrl == 'resources/views/login.php') {
                $location.path('/');
            }
        }
    }
}

【讨论】:

  • 请不要在服务中插入范围。这只是一种糟糕的做法。
  • 是的,你是对的。我只是修改问题中的代码来回答这个问题
【解决方案2】:

非常感谢。采用 Rene M. 提到的关于构建拦截器并让服务器端脚本处理身份验证的方法。

绝对可以,如果返回 403 状态,则将用户重定向到登录页面并更新 isLoggedIn 变量。重构代码以删除 rootScope 的使用,这是一个肮脏的解决方法,直到我掌握了整个角度的身份验证方式。

在下面附上一个简单的例子,以防将来有人偶然发现。

app.config(['$routeProvider', '$locationProvider', '$httpProvider', function ($routeProvider, $locationProvider, $httpProvider) {
    $httpProvider.interceptors.push('responseObserver');

app.factory('responseObserver', ['$location', '$q', function ($location, $q) {
    return {
        'responseError': function (errorResponse) {
            switch (errorResponse.status) {
            case 403:
                //Place logic here
                break;
            case 500:
                //Place logic here
                break;
            }
            return $q.reject(errorResponse);
        }
    };
}]);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-28
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多