如何延迟内联javascript加载时间?

时间:2016-07-16 04:28:15

标签: javascript browser inline delayed-execution

在我的用例中,我使用的是外部和内联的javascript内容。我有以下结构。

  app/
      header.html
      home.html
      config-load.js
      footer.html

home.html包括header.htmlfooter.htmlheader.html文件包含config-load.js

config-load.js根据golang后端的阶段进行ajax调用以获取配置。这可能有几毫秒的延迟。

home.html中的内联脚本很少使用config-load.js ajax调用收集的配置。

因此必须在加载内联脚本之前完成config-load.js ajax调用。但它正在以相反的方式加载。

我尝试使用while循环来延迟内联脚本的加载时间,如下所示,

while(configReceived == false)
{
    setTimeout(function(){
    console.log("waiting for config");
    }, 2000);
}
if(configReceived)
{
    //process configs
}

但这阻止了线程。页面卡在while循环中。还有其他方法可以达到这个目的吗?

编辑1: 这是内联脚本内容,

  <script type="text/javascript">
    window.onload = function() {
        time = new Date($.now());
        var tagsArray = ["C", "C++", "Go", "Ruby"];
        //var tagsArray = [];
        requestJSON = '{"Method":"GET","AppName":"Web-app","ServiceURL":"'+endpoints.Tags.HTTPEndpoint.URL+'","Properties":null,"Object":"","Timestamp":"'+time+'"}'
        $.ajax({
        type: "GET",
        url: endpoints.Tags.HTTPEndpoint.URL,
        data: requestJSON,
        processData: false,
        contentType: "application/json;",
        dataType: "json",
        async: false,
        success: function(data){
          console.log("tags retrieved successfully info updated successfully")
          console.log("Tags ", data.Object)
          tagsArray = data.Object
        },
        failure: function(errMsg) {
            console.log("Error occured in getting tags ", errMsg)
        }
        });
        $("#myTags").tagit();
        $("#tags").tagit({
        fieldName: "tagsName", // The name of the hidden input field
        availableTags: tagsArray,
        allowSpaces:true,
        caseSensitive:false,
        removeConfirmation:true,
        placeholderText:"Tags",
        tagLimit: 5,
        allowDuplicates: false,
        singleField: true, // Use a hidden input element with the fieldName name
        singleFieldDelimiter: ',', // Optional, default value is same.
        onlyAvailableTags: false
        });
    }
 </script>

我的config-load.js如下所示,

//////////////////////////////////////////////////////////
// code block to get the service endpoints by stage starts
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4 && xhr.status == 200) {
      endpoints = JSON.parse(xhr.responseText);
      console.log("server endpoints be ", endpoints);
      configReceived = true;
  }
}
xhr.open("GET", "/config", true);
try {
  xhr.send();
} catch (err) {
  // handle error
  console.log("Error occured in getting the service endpoints. This may break all ajax services");
}
// code block to get the service endpoints by stage ends
////////////////////////////////////////////////////////

我正在尝试最近3天,但没有运气。

2 个答案:

答案 0 :(得分:1)

请注意,javascript是异步的,除非您没有使用async await新的javascript功能或promises,否则您无法完全控制脚本的加载顺序。但在你的情况下并不是真的需要它们。

您需要做的第一件事就是将config-load.js包含在head部分的顶部,这样就可以保证在填充DOM之前加载文件。

另一件事是在内联脚本中使用window.onload函数,强制浏览器仅在构造完全填充所有DOM结构并完全填充后解析脚本。

因此在你的html部分中将你的函数包装到window.onload函数回调:

<script type="text/javascript">
    window.onload = function() {
        while(configReceived == false)
        {
            setTimeout(function(){
            console.log("waiting for config");
            }, 2000);
        }
        if(configReceived)
        {
            //process configs
        }
    }
</script>

修改

您的方法中存在相当多的错误。首先,不需要在两个单独的脚本中调用ajax请求。使用上面提到的承诺技术,您可以链接响应。以下是jquery promises如何工作的简短示例:

function first() {
   return $.ajax(...);
}

function second(data, textStatus, jqXHR) {
   return $.ajax(...);
}

function third(data, textStatus, jqXHR) {
   return $.ajax(...);
}

function main() {
    first().then(second).then(third);
}

记住:链组中的调用会返回响应。这意味着您可以将响应委托给下一个链,这意味着当请求得到解决后,您可以将结果传递给下一个调用。

当您通过调用端点服务收到响应时应用于您的示例,您可以将结果作为参数传递给下一个调用,只有在第一次调用的响应将被解析时才会访问它。

以此fiddle为例。

应用此技术不再需要检查configReceived = true;

您必须确保在尝试调用jQuery.ajax之前包含jQuery。

以下是有关承诺的一些参考资料:

http://www.danieldemmel.me/blog/2013/03/22/an-introduction-to-jquery-deferred-slash-promise/ http://www.bitstorm.org/weblog/2012-1/Deferred_and_promise_in_jQuery.html https://davidwalsh.name/write-javascript-promises

答案 1 :(得分:1)

&#34; while loop&#34;是同步的,这意味着它将阻塞线程并使整个应用程序卡住。

无法保证Javascript异步脚本的执行顺序,因此您应该使用&#34;回调&#34;或者在ES6中你可以使用promise,ES7你可以使用async,等待。

无论如何,更好的方法是将config-load.js javascript代码包装在一个函数中,如果你使用Jquery的ajax api,代码可能如下所示:

function loadConfigAjax(callback){
   $.ajax({url: "http://myconfig", success: function(config){
    callback(config)
}});
}

在你的内联javascript中可能看起来像这样

<script type="text/javascript">
    window.onload = function() {
        var configReceived = function(config){
           //process configs
        };
        // pass the configReceived as callback
        // so that configReceived function will always be invoked after config received
        loadConfigAjax(configReceived);
    }
</script>