如何确保javascript的执行顺序?

虽然现代浏览器可以并行的下载JavaScript(部分浏览器),但考虑到JavaScript的依赖关系,他们的执行依然是按照引入顺序进行的。

为了更好的测试这个过程,我写了一个简单的HTTP处理程序页面 service.ashx,它可以接受两个参数:

  1. file,需要返回文件的服务器端路径。

  2. delay,延迟一定时间后再返回本次HTTP请求(毫秒)。

一个典型的页面比如:./service.ashx?file=js/jquery-ui.js&delay=2000,表示延迟2秒钟后再返回服务器端的js/jquery-ui.js文件。

service.ashx 的关键代码如下:

public void ProcessRequest(HttpContext context)
{
    int delay = 0;
    if (!String.IsNullOrEmpty(context.Request["delay"]))
    {
        delay = Convert.ToInt32(context.Request["delay"]);
    }
    if (delay > 0)
    {
        System.Threading.Thread.Sleep(1000);
    }
    string filePath = context.Request["file"].ToString();
    string fileContent = String.Empty;
    using (StreamReader sr = new StreamReader(context.Server.MapPath(filePath)))
    {
        fileContent = sr.ReadToEnd();
    }
    if (filePath.EndsWith(".js"))
    {
        context.Response.ContentType = "application/x-javascript";
    }
    else
    {
        context.Response.ContentType = "text/plain";
    }
    context.Response.Write(fileContent);
}

通过script标签直接引入JavaScript(test1.htm)

首先我们分析下在<head>标签中顺序引入JavaScript的情况。test1.htm的页面源代码如下:

<html>
<head>
<title></title>
<script src="./js/jquery-1.4.4.js"  type="text/javascript"></script>
<script src="./service.ashx?file=js/jquery-ui.js&delay=2000" type="text/javascript"></script>
    <script>
                 alert(typeof (jQuery.ui));
    </script>
</head>
<body>
</body>
</html>

我们分别在各种浏览器中测试这个例子。

各个主流浏览器的行为一致。虽然jQueryUI在服务器延迟了2秒钟再返回,但是后引入的内联JavaScript还是等待了2秒,等前面引入的JavaScript执行完毕才执行。这也是著名的JavaScript顺序执行的特性。

通过JavaScript添加script标签(test3.htm)

我们首先定义一个addScript函数,用来引入外部或者内联JavaScript。test3.htm的页面源代码如下:

<html>
<head>
    <title></title>
    <script src="./js/jquery-1.4.4.js" type="text/javascript"></script>
    <script>
        function addScript(url, inline) {
            var head = document.getElementsByTagName("head")[0];
            var script = document.createElement('script');
            script.type = 'text/javascript';
            if (inline) {
                script.text = url;
            } else {
                script.src = url;
            }
            head.appendChild(script);
        }
 
        $(function () {
            addScript('./service.ashx?file=js/jquery-ui.js&delay=2000');
            addScript('alert(typeof(jQuery.ui));', true);
        });
    </script>
</head>
<body>
    <div id="container">
    </div>
</body>
</html>

可见,通过JavaScript在DOM加载完毕后再引入外部或者内联JavaScript时,Firefox和Opera的行为一致,能够确保JavaScript的执行顺序和引入顺序一致。但是IE8, Chrome, Safari 却不能保证这个执行顺序。

虽然各种浏览器在确保执行顺序方面不尽相同,不过这时的最大好处是多个JavaScript文件能够并行下载,这在所有浏览器中行为一致。

如何解决各个浏览器的不一致性,下面提供了两个解决方案:

方案一,如何在动态添加script标签时确保执行顺序

有时页面逻辑要求我们必须通过上面的方式动态执行JavaScript,那么如何确保所有浏览器下的执行顺序(目前只有Firefox和Opera确保执行顺序)。

其实解决方案很简单,我们为函数执行添加一个complete的回调函数就行了。下面的test4.htm给出了具体的解决方案:

<html>
<head>
    <title></title>
    <script src="./js/jquery-1.4.4.js" type="text/javascript"></script>
    <script>
        function addScript(url, inline, callback) {
            var head = document.getElementsByTagName("head")[0];
            var script = document.createElement('script');
            script.type = 'text/javascript';
            if (inline) {
                script.text = url;
            } else {
                script.src = url;
                script.onload = script.onreadystatechange = function () {
                    if (!script.readyState || script.readyState === 'loaded' ||
                     script.readyState === 'complete') {
                        if (callback) {
                            callback();
                        }
                        script.onload = script.onreadystatechange = null;
                    };
                };
            }
            head.appendChild(script);
            if (inline && callback) {
                callback();
            }
        }
 
        $(function () {
            addScript('./service.ashx?file=js/jquery-ui.js&delay=2000', false, function () {
                addScript('alert(typeof(jQuery.ui));', true);
            });
        });
    </script>
</head>
<body>
    <div id="container">
    </div>
</body>
</html>

此时所有浏览器中的行为一致。

方案二,使用jQuery的html函数动态添加JavaScript

jQuery的html函数用来更新一个DOM片段,我们可以很方便的通过这个函数来动态加载JavaScript,请看示例test2.htm:

<html>
<head>
    <title></title>
    <script src="js/jquery-1.4.4.js" type="text/javascript"></script>
    <script>
        $(function(){
            $('#container').html('
            <script src="./service.ashx?file=js/jquery-ui.js&delay=2000" type="text\/javascript">
            <\/script>' + '<script>alert(typeof(jQuery.ui));<\/script>');
        });
    </script>
</head>
<body>
    <div id="container">
    </div>
</body>
</html>

此时,各个浏览器中的行为一致。

更多前端开发知识,请查阅 HTML中文网 !!

以上就是如何确保javascript的执行顺序?的详细内容,更多请关注web前端其它相关文章!

赞(0) 打赏
未经允许不得转载:web前端首页 » JavaScript 答疑

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

前端开发相关广告投放 更专业 更精准

联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏