如何强制某些Javascript片段在其他之前加载?

时间:2017-02-26 20:38:09

标签: javascript html

这是我的HTML页面的完整副本,因此您可以看到我在谈论的内容:

<!doctype html>

<html lang="en">
<head>
<meta charset="utf-8">
<title>Test Page</title>
<meta name="robots" content="noindex, nofollow">

<script type="text/javascript">
_atrk_opts = { atrk_acct:"/123456", domain:"example.com",dynamic: true};
(function() { var as = document.createElement('script'); as.type = 'text/javascript'; as.async = true; as.src = "https://123.cloudfront.net/sample.js"; var s = document.getElementsByTagName('script')[0];s.parentNode.insertBefore(as, s); })();
</script>

<script type="text/javascript">
_atrk_opts = { atrk_acct:"/tester", domain:"other.com",dynamic: true};
(function() { var as = document.createElement('script'); as.type = 'text/javascript'; as.async = true; as.src = "https://123.cloudfront.net/sample.js"; var s = document.getElementsByTagName('script')[0];s.parentNode.insertBefore(as, s); })();
</script>

<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-91071000-1', 'auto');
  ga('send', 'pageview');

</script>

</head>

<body>
<script>
window.location = "http://test.com";
</script>
</body>

</html>

我在标题中有3个脚本,我需要在运行正文中的Javascript重定向之前完全运行。

所有脚本都会加载像素,并用于分析跟踪。基本上我遇到的问题是,只有一部分访问者被跟踪,因为在标题中的片段完成之前,正文中的重定向正在运行。

我更倾向于在实际重定向访问者之前保证javascript运行的解决方案 - 我已经离开,我可以设置一个计时器在X秒后运行我的重定向,但是没有办法知道如果其他脚本完成(尽管它们应该非常快)。

任何建议或解决方案都会很棒。谢谢!

3 个答案:

答案 0 :(得分:1)

您可以使用setTimeout()将脚本延迟几秒钟:

setTimeout(function(){
  window.location = "http://test.com";
}, 3000); // Delays the execution by 3 seconds

或者,如果您有权访问jQuery,最好使用.ready()来确保页面已完全加载:

$(document).ready(function() {
    window.location = "http://test.com";
});

Google Analytics也有hitCallback可用于确保其脚本已完成运行,您可以通过添加事件监听器来检查这些脚本:

var body = document.getElementById('body');
body.addEventListener('submit', function(event) {
  event.preventDefault();
  ga('send', 'event', 'pageview', 'submit', {
    hitCallback: function() {
      window.location = "http://test.com";
    }
  });
});

这将确保分析在重定向发生之前实际运行。

希望这有帮助! :)

答案 1 :(得分:1)

3个函数异步运行。您可以修改正文中的页面重定向代码,以便在继续之前检查这些函数的结果。

例如,看起来这三个函数会在文档中插入新节点,因此您可以定期检查代码是否存在以下行:

var timer = setTimeout(function(){
   // Check for elements
   if(document.querySelector(...)){
     // Elements(s) exist, cancel timer
     clearTimeout(timer);

     // Proceed with rest of code
   }
}, 1000);

此外,无需将它们分隔为单独的<script>元素。

答案 2 :(得分:1)

如果所有分析API都不支持点击完成时的回调,那么您需要自己添加一个。

下载并修改其分析js文件并使用它而不是您当前拥有的注入代码。或者根本不使用他们的代码,只需自己构建带有所需信息的图片网址。

在这两种情况下,您都需要使用网址将请求发送到分析服务器,然后在完成后执行重定向。在现代浏览器中使用PromiseFetch api:

//so either in the analytics code or your own manual code
var img = new Image();
var analyticsUrl = "http://analytics.example.com/?id="+yourid+"&os="+useros+"&country="+usercountry;

fetch( new Request(analyticsUrl,{mode:"no-cors"}) ).then(()=>{
   window.location = "your url";
});

//In the case of multiple analytics packages you would just put the fetches in an array and pass it to Promise.all

var promise1 = fetch( new Request(analyticsUrl1,{mode:"no-cors"}) );
var promise2 = fetch( new Request(analyticsUrl2,{mode:"no-cors"}) );
var promise3 = fetch( new Request(analyticsUrl3,{mode:"no-cors"}) );
Promise.all([ promise1, promise2, promise3 ]).then(()=>{
   window.location = "your url";
});

在较旧的浏览器上,可能不支持这些浏览器。

因此,如果您想要支持这些旧版浏览器,则需要在添加到dom的图像上添加onload事件侦听器。在事件监听器中,您需要测试是否已完成其他操作,然后再进行重定向,如果是这样的话。

var loaded = 0;
function onAnalyticsLoad(){
   loaded++;
   if(loaded >= 3){ 
      window.location = "your url"; 
   }
}
//don't care if there was an error or not, just care that 
//the request had at least time to finish so use both onload and onerror.
analyticsImg1.onload = analyticsImg1.onerror = onAnalyticsLoad;
analyticsImg2.onload = analyticsImg2.onerror = onAnalyticsLoad;
analyticsImg3.onload = analyticsImg3.onerror = onAnalyticsLoad;