资源加载跟踪
浏览器允许我们跟踪外部资源的加载情况
- 脚本 script
- iframe
- 图片等
一共涉及两个事件
- onload 事件
- onerror 事件
加载脚本
当我们使用动态脚本引入外部资源时,如果我们想要在脚本加载并执行完成后调用其中的函数,可以这么做
javascript1let script = document.createElement('script') 2 3// 可以从任意域(domain),加载任意脚本 4script.src = 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.js' 5document.head.append(script) 6 7script.onload = function () { 8 // 该脚本创建了一个变量 "_" 9 alert(_.VERSION) // 显示库的版本 10} 11//如果加载失败,则会进入这个函数 12script.onerror = function () { 13 alert('Error loading ' + this.src) // Error loading 14}
如果是我们自己写的脚本,则可以使用
module的方式来引入即可,这里列举外部引入的脚本
重要:
onload/onerror 事件仅跟踪加载本身。
在脚本处理和执行期间可能发生的 error 超出了这些事件跟踪的范围。也就是说:如果脚本成功加载,则即使脚本中有编程 error,也会触发 onload 事件。如果要跟踪脚本 error,可以使用 window.onerror 全局处理程序。
加载其他资源
load 和 error 事件也支持加载其他资源,基本上适用于所有有src属性的资源,比如下面是加载图片
javascript1let img = document.createElement('img') 2img.src = 'https://js.cx/clipart/train.gif' 3 4img.onload = function () { 5 alert(`Image loaded, size ${img.width}x${img.height}`) 6} 7 8img.onerror = function () { 9 alert('Error occurred while loading image') 10}
对于 iframe 来说,iframe 加载完成后会触发 iframe.onload 事件,无论成功还是出现 error
跨域脚本策略
script标签的 src一般会越过跨域问题,在 script请求对方资源时,会有以下细节
script请求资源时,request header 不会带有 origin 头script请求资源时,如果对方的脚本出现 error,那么通过本方的window.onerror事件没办法获取到详细的 error 信息
以下代码就是获取对方脚本资源,但是却打不出详细的 error 信息
html1<script> 2 window.onerror = function (message, url, line, col, errorObj) { 3 alert(`${message}\n${url}, ${line}:${col}`) 4 } 5</script> 6<script src="https://cors.javascript.info/article/onload-onerror/crossorigin/error.js"></script>
这是因为这个 error 信息来自其他源。
要允许跨域访问,于是script也需要具有 crossorigin特性,并且远程服务器也需要提供 header 告诉浏览器运行跨域
这里有两个属性可以设置
crossorigin="anonymous"匿名访问——如果对方的响应中的header中的Access-Control-Allow-Origin带有*或者我们的 origin,则允许访问。浏览器不会授权信息和 cookie 发送给远程服务器crossorigin="use-credentials"使用资格——如果对方的响应中的header中的Access-Control-Allow-Origin带有我们的源并且Access-Control-Allow-Credentials: true.则允许访问。且浏览器会授权信息和 cookie 发送给远程服务器
常见情况是不会给对方发送 cookie的,我们只是需要对方的错误信息,所以我们将上面的代码加上crossorigin="anonymous"
属性,这时候就可以看到完整的错误信息了
html1<script> 2 window.onerror = function (message, url, line, col, errorObj) { 3 alert(`${message}\n${url}, ${line}:${col}`) 4 } 5</script> 6<script src="https://cors.javascript.info/article/onload-onerror/crossorigin/error.js"></script>
小结
- 图片 img 外部样式 iframe 等资源都可以通过
load和error事件跟踪它们的加载情况 - iframe 不管加载成功或者失败都只会触发 load 事件,这可能是处于历史原因
- script 标签在加载时也可能需要跨域,这时候可以设置
crossorigin属性