IE下script标签的readyState属性
在做加载器时遇到一个常见问题,如何判定一个脚本已经执行完毕。
- “uninitialized” – 原始状态
- “loading” – 下载数据中
- “loaded” – 下载完成
- “interactive” – 还未执行完毕
- “complete” – 脚本执行完毕.
网上流行的答案是这个,我怎么觉得其实这是抄自XMLHttpRequest的readyState呢?!恰逢这两个都有这属性。
我们亲自做一个实验:
<!DOCTYPE html>
<html>
<head>
<title>node.readyState</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script>
var node = document.createElement("script")
node.onreadystatechange = function() {
var state = node.readyState
setTimeout(function() {
var div = document.createElement("div")
document.body.appendChild(div)
div.innerHTML = state
}, 300) }
var head = document.getElementsByTagName("head")[0]
head.appendChild(node)
node.src = "avalon.js" </script>
</head>
<body>
<div>node.readyState</div>
</body>
</html>
| 完整的控件教程 | |
|---|---|
| IE11 | 空白,说明完全与标准一致了 |
| IE10 | loading loaded |
| IE9 | loading loaded |
| IE8 | complete loaded |
| IE7 | complete loaded 但有一定机率,只出现complete或loaded |
| IE6 | complete loaded 但有一定机率,只出现complete或loaded |
换言之,IE67是个非常悲催的问题。另外,opera9-10也支持readyState,根据老外的描述,它竟然两次都是loaded!
因此我们需要根据浏览器的情况采用不同的策略。
首先是使用何种回调,如果是支持onload事件,那么就直接用onload 就没有这么多麻烦事。最简单的策略是这样判定:
var node = DOC.createElement("script")
var supportLoad = "onload" in node
var onEvent = supportLoad ? "onload" : "onreadystatechange"
node[onEvent] = callback
判定完成时机, 我们不使用网上的/complete|loaded|undefined/.test(node.readyState),这会同时掉进opera与IE67的坑中。对于使用onload事件进行监听的,不再判定node.readyState,IE(其实也就是IE6-8),需要使用一个定时器。当第一次进行onreadystatechange回调时,timeID为空, 并且readyState为complete或loaded时,我们设置它在300ms后再执行自身。然后如果浏览器还执行此回调时, 它就进入第二个分支,清掉定时器,执行用户代码。万一,浏览器只执行一次onreadystatechange回调,那也没关系,让定时器100~300ms后执行用户代码
最后贴出全部代码:
//通过script节点加载目标模块
var node = DOC.createElement("script")
var timeID
var supportLoad = "onload" in node
var onEvent = supportLoad ? "onload" : "onreadystatechange"
node[onEvent] = function onLoad() {
if (!supportLoad && !timeID && /complete|loaded/.test(node.readyState)) {
timeID = setTimeout(onLoad)
return
}
if (supportLoad || timeID) {
clearTimeout(timeID)
//你的代码
}
}
head.insertBefore(node, head.firstChild) //chrome下第二个参数不能为null
node.src = url //插入到head的第一个节点前,防止IE6下head标签没闭合前使用appendChild抛错
大家也可以到这里看一下它的实际应用,如果大家都是使用AMD规范定义JS文件,那么我在旧式IE下连onerror也模拟出来了。
IE下script标签的readyState属性的更多相关文章
- [转]HTML5 script 标签的 crossorigin 属性到底有什么用?
HTML5 script 标签的 crossorigin 属性到底有什么用? 最近Bootstrap 4已经正式发布了,可能已经有爱尝鲜的小伙伴在 alpha 阶段就尝试过 BS4.不过今天要说的不是 ...
- 怎样理解script标签的defer属性和async属性
如果script标签是引用的外部js文件, 那就会有一个下载js文件这一过程, 为了不因为这个下载过程而阻塞页面解析与渲染, 我们需要一种机制来解决这一问题, 方法之一就是使用 defer和async ...
- html中script标签使用async属性和defer属性的区别
相同点: 首先async和defer只对header里的外连脚本script标签上起作用,如果script标签是放在header外或者是header里的内置脚本以及动态生成的script标签是不起作用 ...
- script标签不带属性与带async、defer的区别
<script> 当页面解析到script标签时,会停止解析并下载对应的脚本,并马上执行,执行完毕后再继续解析页面 <script async> async 在下载脚本的同时不 ...
- script标签的crossorigin属性
通常我们使用window.onerror来捕获js脚本的错误信息. 但是对于跨域调用的js脚本,onerror事件只会给出很少的报错信息:error: Script error. 这个简单的信息很明显 ...
- select标签下option标签里value属性有什么用以及和text的区别
转自:http://blog.csdn.net/summer_sy/article/details/54572398 1:value的用处 <select > <option val ...
- script标签属性sync和defer
<script src="a.js" defer></script> 加了defer属性script标签的页面,运行流程如下: 1.浏览器开始解析HTM ...
- 如何将 JavaScript 代码添加到网页中,以及 <script> 标签的属性
Hello, world! 本教程的这一部分内容是关于 JavaScript 语言本身的. 但是,我们需要一个工作环境来运行我们的脚本,由于本教程是在线的,所以浏览器是一个不错的选择.我们会尽可能少地 ...
- script标签crossorigin属性及同源策略和跨域方法
首先介绍(同源策略) 同源策略是浏览器最核心且基本的安全约定,要求协议.域名.端口都相同为同源,如果非同源时请求数据浏览器会在控制台抛出跨域异常错误,同源策略是浏览器的行为,即使客户端请求发送了,服务 ...
随机推荐
- C语言实现二叉树的建立、遍历以及表达式的计算
实现代码 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <ctype ...
- 用Emacs的这些年
读技术博客时发现又有人提起我曾写的那篇口水文章 为何Emacs和Vim被称为两大神器.写那篇文章时,我还在Vim和Emacs之间摇摆.当然主要在用vim,博士学位论文和所有的国际会议文章都是用Vim编 ...
- Java——Struts2 之国际化 struts.custom.i18n.resources=globalMessages
1.在src下 建立 struts.properties 文件,内容为:struts.custom.i18n.resources=globalMessages struts.custom.i18n.r ...
- ms sqlserver2008r2 自动备份
日常工作中利用SQL SQLSERVER 2008 的维护计划对数据库进行定期的备份,这样一方面可以对数据库进行备份保证数据安全另一方面也可以减轻对维护人员的负担. 一般对于WEB 服务器进 行维护都 ...
- JavaScript之浏览器兼容问题与IE(神经病一样的浏览器)
IE是最讨厌的浏览器,没有之一.----题记 废话不说,粘上大图~
- Managers经理/代理形式的数据共享
代理方式实现进程间共享字典和列表形式的数据, 代码块: import os from multiprocessing import Process,Manager def f(d,l,normalLi ...
- 下拉框combobox用法&级联餐单
如果下来内容不用后台取数据,直接写死的话不用url属性,直接用data即可: <input id="orderstate" name="orderstate&quo ...
- Python的虚拟环境virtualenv
原文地址:blog.sina.com.cn/s/blog_4ddef8f80101eu0w.html Python的虚拟环境可以使一个Python程序拥有独立的库library和解释器interpre ...
- mysql 8.0 ~ 安装
1 环境配置 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.13-linux-glibc2.12-x86_64.tar. ...
- script标签中type为"text/x-template"或"text/html"
写过一点前端的都会碰到需要使用JS字符串拼接HTML元素然后append到页面DOM树上的情况,一般的写法都是使用+号以字符串的形式拼接,如果是短点的还好,如果很长很长的话就会拼接到令人崩溃了. 比如 ...