简体   繁体   English

Google+登录按钮并不总是加载

[英]Google+ Sign-in button does not always load

I have the following Javascript on the bottom of my index.html : 我的index.html底部有以下Javascript:

<script>
  function signInCallback(authResult) {
    if (authResult.code && authResult.access_token) {
      if (authResult['g-oauth-window']) {
        $.post('/auth/google/callback', {code: authResult.code, access_token: authResult.access_token}).done
          (function(data) {
            window.location.href = data.redir;
          });
      }
    }
  };

  (function() {
    $('#button-address').tooltip();
    var po = document.createElement('script');
    po.type = 'text/javascript';
    po.async = true;
    po.src = 'https://apis.google.com/js/client:plusone.js';
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(po, s);
  })();
</script>

...as well as this HTML in the template of an Angular directive: ...以及Angular指令模板中的此HTML:

<div id="signinButton">
  <span
    class="g-signin"
    data-scope="email"
    data-clientid="CLIENTID.apps.googleusercontent.com"
    data-redirecturi="postmessage"
    data-accesstype="offline"
    data-cookiepolicy="single_host_origin"
    data-callback="signInCallback">
  </span>
</div>

This code renders a Google+ sign-in button on my Angular app's sign-in page. 此代码会在我的Angular应用程序的登录页面上呈现Google+登录按钮。 The problem is ~30% of the time the button does not render and the user needs to refresh the page until it appears. 问题是按钮不呈现的时间约为30%,用户需要刷新页面直到它出现。 I believe this occurs because sometimes the #signinButton div has not been rendered before the JS is run. 我相信这是因为有时候#signinButton div在JS运行之前还没有被渲染。 Does this sound like it could be the issue, and if so how can I delay the JS running until the #signinButton div has been rendered to assure the button always appears? 这听起来像是问题,如果是这样的话,我怎么能延迟JS运行直到#signinButton div被渲染以确保按钮总是出现?

You need to modify this to work within Angular's lifecycle: document.ready is when Angular starts setting up the DOM, not when it's finished. 你需要修改它才能在Angular的生命周期内工作: document.ready是Angular 开始设置DOM的时候,而不是在它完成时。 Depending on document.ready or just dropping code in at the end of the page sets up a potential race condition because there is no guarantee that the DOM node you want to attach events to exists yet (it'll only work if the injected script's load time takes long enough for Angular to have finished rendering by the time the script arrives. Which means on any but the first, non-cached visit it's guaranteed not to work.) 取决于document.ready或者只是在页面末尾删除代码会设置潜在的竞争条件,因为无法保证您想要将事件附加到的DOM节点存在(它只有在注入的脚本加载时才有效)时间需要足够长的角,以完成由脚本到达时间进行渲染。这意味着在任何但是第一,非缓存访问它肯定无法正常工作。)

Assuming the script at client:plusone.js expects to see an existing DOM node #signinButton when linked, you can ensure that the node will exist by including it as part of the directive that renders #signinButton : 假设client:plusone.js的脚本client:plusone.js希望在链接时看到现有的DOM节点#signinButton ,您可以通过将其包含在呈现#signinButton的指令的一部分来确保该节点存在:

var app = angular.module("foo", []);
app.directive('signinButton', function($timeout) {
  return {
    template: '<div id="signinButton">...etc...</div>',
    link: function() {
      var s = document.getElementsByTagName("script")[0];
      var url = 'https://apis.google.com/js/client:plusone.js';
      if (s.src !== url) { /* Don't re-insert the script if it's already there */
        $timeout(function() { // force this to run in the next $digest, after the directive template is rendered
          var po = document.createElement('script');
          po.type = 'text/javascript';
          po.async = true;
          po.src = url;
          s.parentNode.insertBefore(po, s);
        });
      }
    }
  }
});

(The callback function isn't time-sensitive; it can stay at the end of the document as you have now, since that's apparently where client:plusone.js expects to find it, or you could also attach it to the window object from within the directive.) (回调函数不是时间敏感的;它可以像现在一样保留在文档的末尾,因为那显然是client:plusone.js期望找到它,或者你也可以将它附加到窗口对象在指令内。)

Since it is an AngularJS application why don't you use a directive like this one: angular-directive.g-signin ? 既然它是一个AngularJS应用程序,为什么不使用像这样的指令: angular-directive.g-signin The example is pretty self-explanatory. 这个例子非常明显。

put it your function call in $(document).ready() maybe solves your problem? 把你的函数调用放在$(document).ready()可能解决你的问题?

$(document).ready(function(){
    $('#button-address').tooltip();
    var po = document.createElement('script');
    po.type = 'text/javascript';
    po.async = true;
    po.src = 'https://apis.google.com/js/client:plusone.js';
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(po, s);
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM