【问题标题】:Ionic : no content / white screen using interceptors离子:没有内容/使用拦截器的白屏
【发布时间】:2015-06-03 07:31:04
【问题描述】:

我成功地在我的 Ionic 应用程序中使用了拦截器 (AngularJs)。 Previous post.

虽然它在使用“离子服务”的浏览器中运行良好。

标题标题和内容块(“ion-content”)中没有使用“ionic run android”(在 genymotion 或我自己的手机上模拟)加载任何内容。请看下面的截图。

我很确定它来自我正在使用的拦截器,因为在此之前,该应用程序可以在任何平台上运行。此外,一旦我移除拦截器,它就会再次工作。代码在这里。

请注意,我正在检查调用了哪个 url,因此我不会进入循环依赖或检查无用的 url,只有对我的 api 的调用会通过。

app.config(function($httpProvider){

    $httpProvider.interceptors.push(['$location', '$injector', '$q', function($location, $injector, $q){

        return {

            'request' : function(config){

                // intercept request

                // carefull includes might not work while emulating
                // use instead indexOf for that case
                if(!config.url.includes('/oauth/v2/token') && config.url.includes('/api')){

                    // inject the service manually
                    var OauthService = $injector.get('OauthService');

                    var access_token = OauthService.token();
                    config.url = config.url+'?access_token='+access_token.key;

                }

                return config;
            }

        }

    }]);

});

任何想法可能会导致此错误? (顺便说一句,控制台在浏览器上没有显示错误)。

更新:

OauthService.js:

app.factory('OauthService', function($http, $localStorage) {

return {
    token : function(){

        // Store actual token
        access_token = $localStorage.getObject('access_token');
        // Store actual identity
        identity_token = $localStorage.getObject('identity_token');

        // IF no user logged
        if(isObjectEmpty(identity_token)){

            // IF access_token does NOT exist OR will expires soon
            if( isObjectEmpty(access_token) || Date.now() > (access_token.expires_at - (600*1000)) ){

                // Create an anonymous access_token
                return $http
                    .get(domain+'/oauth/v2/token?client_id='+public_id+'&client_secret='+secret+'&grant_type=client_credentials')
                    .then(function (response) {

                        $localStorage.setObject('access_token', {
                            key: response.data.access_token,
                            type: 'anonymous',
                            expires_at: Date.now()+(response.data.expires_in*1000)
                        });

                        return response.data.access_token;

                    });
            }

        }
        // IF user is logged
        else{

            // IF access_token does NOT exist OR will expires soon OR is anonymous
            if( isObjectEmpty(access_token) || Date.now() > (access_token.expires_at - (600*1000)) || access_token.type == 'anonymous' ){
                // Create an access_token with an identity
                return $http
                    .get(domain+'/oauth/v2/token?client_id='+public_id+'&client_secret='+secret+'&api_key='+identity_token+'&grant_type=http://oauth2.dev/grants/api_key')
                    .then(function (response) {

                        $localStorage.setObject('access_token', {
                            key: response.data.access_token,
                            type: 'identity',
                            expires_at: Date.now()+(response.data.expires_in*1000)
                        });

                        return response.data.access_token;

                    });
            }

        }

        return access_token.key;

    }
};

})

【问题讨论】:

  • 您是否在OauthService.token() 中返回承诺?
  • 我不这么认为,我对承诺/延迟的概念有点陌生。我用 OauthService 源代码更新了帖子。
  • 但是在第一次启动时它不应该调用 api(登录页面)。所以我们还没有经历这个条件,它已经显示了一个白屏。我想知道拦截器是否没有弄乱我的路线。
  • 我猜是的。检查我更新的答案。处理不记名令牌的拦截器应该如何工作有一个粗略的想法。

标签: angularjs cordova ionic-framework ionic


【解决方案1】:

你安装了cordova whitelist plugin 吗?

cordova plugin add cordova-plugin-whitelist

或者如果您想保存对 config.xml 文件的引用:

cordova plugin add cordova-plugin-whitelist --save

如果没有,您的设备将无法访问外部资源。

您可以找到更多信息here

更新

我已经检查了您之前的答案。
拦截器的想法是拦截对外部服务的调用,在管道中插入一些操作。

我会改变你的拦截器:

$httpProvider.interceptors.push(['$location', '$injector', '$q', '$localStorage', function($location, $injector, $q, $localStorage){

    return {

        'request' : function(config) {
            config.headers = config.headers || {};

            access_token = $localStorage.getObject('access_token');

            if (access_token) {
                config.headers.Authorization = 'Bearer ' + access_token;
            }
        }

        'response' : function(response){

            if (response.status === 401) {
                logger.debug("Response 401");
            }
            return response || $q.when(response);
        }

        'responseError' : function(rejection){

            if (rejection.status === 401) {
                var OauthService = $injector.get('OauthService');
                var access_token = OauthService.token();

                if (access_token === null)
                {
                    return $q.reject(rejection);
                }

                // Append your access token to the previous request and re-submits.
                rejection.config.headers['Authorization'] = 'Bearer ' + access_token;
                return $injector.get('$http')(rejection.config);
            }

            // This is necessary to make a `responseError` interceptor a no-op. 
            return $q.reject(rejection);
        }
    }
}]);

如果您查看上面的拦截器,它会管理对外部资源 (REST api) 的所有请求,并在需要时将不记名令牌附加到授权标头。

响应没有太多作用,因为它只是用于记录目的。

responseError 是你应该拦截并检查你的令牌是否过期的地方,获取一个新的并重新提交请求。

我们检查用户是否没有被授权的请求:

if (rejection.status === 401) { ... }

如果不是,我们请求一个新的访问令牌。我猜你的 OauthService 就是这样做的。 如果我们有新的访问令牌:

var access_token = OauthService.token();

我们可以再次将访问令牌附加到请求标头:

rejection.config.headers['Authorization'] = 'Bearer ' + access_token;

并重新提交之前的请求:

return $injector.get('$http')(rejection.config);

如果你想了解更多关于拦截器的信息,你可以readtheseblogs

【讨论】:

  • 是的,我已经在使用它了。我可以在没有拦截器的情况下访问外部资源。
  • responseError 允许我从之前的代码中找到错误之一。模拟时无法识别包含,因此我将其替换为 indexOf 并且它正在工作。无论如何,我会继续挖掘,您的解决方案有点复杂,所以我需要更多时间来实现它。我不确定如何使用标头,因为我在 url 中使用访问令牌调用我的 api,而不是在标头中。
  • 而rejection.status 也起到了部分作用。谢谢!
  • 很高兴我能帮上忙。我的答案中包含了一些链接。您可以找到很多关于拦截器及其工作原理的有用信息。干杯。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多