如何在app.run中使用异步代码?

时间:2014-11-27 18:19:00

标签: javascript angularjs angularjs-scope

我有一个运行块,它正在查询我的服务器以检查用户是否已通过身份验证。

.run(function($http, userService){
    var base_url = 'http://server.com:3000';

    $http.get(base_url + '/users/isloggedin')
        .success(function(data, status, headers, config){
            userService.setUserData(data.userData);
            userService.setIsUserLoggedIn(true);
        });
})

稍后,我有另一个需要第一个运行块信息的运行。这个问题是我的运行代码有异步代码,我第一次没有得到userService.getIsUserLoggedIn()的真值。

如何判断angularjs仅在第一个运行块完成后执行第二个运行块?

第二个运行块:

.run(function($rootScope, $location, $state, userService){
    //Run to handle authentication

    var authOnly = ['/painel'];
    var unAuthOnly = ['/home'];

    var checkAuthRoute = function(url){
        var exist = authOnly.indexOf(url);
        return exist > -1;
    };

    var checkUnAuthRoute = function(url){
        var exist = unAuthOnly.indexOf(url);
        return exist > -1;
    };

    $rootScope.$on('$stateChangeStart', function(evt, toState, toParams, fromState, fromParams){
        console.log(toState.url + ' ' + fromState.url + ' - ' + userService.getIsUserLoggedIn());

        if(!userService.getIsUserLoggedIn() && checkAuthRoute(toState.url)){
            console.log('Aqui..');
            evt.preventDefault();
            $state.go('login');
        }

    });
})

由于

2 个答案:

答案 0 :(得分:1)

您可以使用回调在Javascript中创建链异步请求。这样的事情可能有用:

.run(function($http, $rootScope, $location, $state, userService){
    var base_url = 'http://server.com:3000';

    $http.get(base_url + '/users/isloggedin')
        .success(function(data, status, headers, config){
            userService.setUserData(data.userData);
            userService.setIsUserLoggedIn(true);
            handleAuth($rootScope, $location, $state, userService);
        });
})

在上面的.run代码之前定义此函数:

function handleAuth($rootScope, $location, $state, userService){
    var authOnly = ['/painel'];
    var unAuthOnly = ['/home'];

    var checkAuthRoute = function(url){
        var exist = authOnly.indexOf(url);
        return exist > -1;
    };

    var checkUnAuthRoute = function(url){
        var exist = unAuthOnly.indexOf(url);
        return exist > -1;
    };

    $rootScope.$on('$stateChangeStart', function(evt, toState, toParams, fromState, fromParams){
        console.log(toState.url + ' ' + fromState.url + ' - ' + userService.getIsUserLoggedIn());

        if(!userService.getIsUserLoggedIn() && checkAuthRoute(toState.url)){
            console.log('Aqui..');
            evt.preventDefault();
            $state.go('login');
        }

    });
}

一个更受欢迎的替代方案(为了防止使代码不可读的回调的不断链接 - 也就是末日金字塔),是使用{{3} }。

promise使用异步函数,返回一个promise,您可以使用它来链接请求(例如,$ http方法返回您使用的名为success的promise) 。它在ECMAScript 5中不可用,但将在6中。人们已经做了许多Promises的实现,比如Kris Kowal的Q,而Angular有一个名为$q的这个库的精简版本。

答案 1 :(得分:0)

因为这是异步调用,所以技术上第一个块已经完成,但是其中的调用不是。我想到的唯一一件事就是在userService中添加promise并通过它进行通信:

.run(function($http, $q, userService){
    var base_url = 'http://server.com:3000';
    var deferred = q.defer();
    $http.get(base_url + '/users/isloggedin')
        .success(function(data, status, headers, config){
            userService.setUserData(data.userData);
            userService.setIsUserLoggedIn(true);
            deferred.resolve();
        });
    userService.setPromise(deferred.promise);
})

在第二轮中:

.run(function(userService){
        userService.getPromise().then(function(){
           //code that requires first run to finish
        });
    })

但是如果某个地方需要从第二次运行完成代码(我的意思是只在第二次运行后才进行smth),它将再次需要相同的结构,并且这不是很好,所以你需要改变逻辑。