在GAE / Angular应用程序中的window.init()上的无限循环

时间:2015-02-26 00:57:36

标签: javascript angularjs google-app-engine

我正在使用带有AngularJS的cloud enpoints演示,并且我在加载client.js之后使用他们建议的运行授权的方法进入无限循环。这是建议的方法。

首先,在所有其他脚本标签之后(对于Angular和其他JS文件,我正在这样做):

<script>
    function init() {
        window.init();
    }
</script>
<script src="https://apis.google.com/js/client.js?onload=init"></script>

然后,在控制器中,我处理窗口init,如:

    $window.init = function () {
        // Loads the OAuth and helloworld APIs asynchronously, and triggers login
        // when they have completed.
        var apisToLoad;
        var callback = function () {
            if (--apisToLoad == 0) {
                googleAPI.signin(true,
                    googleAPI.userAuthed);
                appContext.appReady = true;
                alert('loaded');
            }
        }

        apisToLoad = 2; // must match number of calls to gapi.client.load()
        gapi.client.load('helloworld', 'v1', callback, googleAPI.apiRoot);
        gapi.client.load('oauth2', 'v2', callback);
    };

我认为我发现这里有一个竞争条件,$ window.init没有及早设置,所以我最终得到了消息:

  

未捕获RangeError:超出最大调用堆栈大小

这是因为“window.init()”只是回调init()函数并超出堆栈。

有关如何更好地处理此事的任何建议?感谢。

4 个答案:

答案 0 :(得分:2)

看起来您的角度控制器没有及时加载/执行,无法告诉原因,但您可以等待文档就绪,以真正的jQuery方式:

function init() {
    angular.element(document).ready(function() {
        window.init();
    });
}

Angular应该在那之前完成加载。

答案 1 :(得分:2)

第一行是在那里创建一个无限循环,因为你在实际的window.init中调用了window.init。

<script>
    /**
     * Initializes the Google API JavaScript client. Bootstrap the angular module after loading the Google libraries
     * so that Google JavaScript library ready in the angular modules.
     */
    function init() {
        gapi.client.load('conference', 'v1', null, '//' + window.location.host + '/_ah/api');
        gapi.client.load('oauth2', 'v2', callback);
    };
</script>
<script src="//apis.google.com/js/client:plusone.js?onload=init"></script>

您可以尝试使用此代码来查看是否对您更有意义

答案 2 :(得分:1)

通过这样做,你告诉window.init调用自己,创建一个无限循环。

<script>
    function init() {
        window.init();
    }
    init===window.init; // => true
</script>
<script src="https://apis.google.com/js/client.js?onload=init"></script>

如果你仔细看一下my code,你会发现我对这些功能的命名方式不同,如下所示:

<script>
    function init() {
        window.initGapi();
    }
    init===window.initGapi; // => false
</script>
<script src="https://apis.google.com/js/client.js?onload=init"></script>

然后只需在控制器中定义initGapi

$window.initGapi = function () {}

对已接受答案的评论中的代码会等到api加载到引导应用程序,这需要更长的时间。

答案 3 :(得分:0)

把它放在“我错过了一些非常基本的东西”垃圾箱里:

我注意到我在控制器定义中遗忘了一些内容:

topNavBar.$inject = ['$location', 'appContext', 'logger'];
function topNavBar($location, $window, appContext, logger) {

注意,注入中没有'$ window',因此它获得了appContext的定义并且执行“$ window.init =”绝对没有效果。