有关scrip标签、async与defer区别

文章详细讨论了HTML中script标签的用法,包括src属性设定外部脚本、defer和async属性对加载顺序的影响,以及crossorigin属性在跨域脚本加载中的作用。当script加载SDK时,即使内部有错误,也不会影响当前脚本执行,但调用SDK方法时需注意错误处理。动态创建script标签可以实现异步加载,通过onload回调确保执行顺序。
摘要由CSDN通过智能技术生成

1. script指定src后内部代码无效

<script src='/test.js'>
    console.log(222) // 不会执行
</script>
 <script src='/test.js'></script>
 <script>
     console.log(222) // 可以执行
 </script>

2. async 和 defer

async与defer的区别:
defer和async都是让script异步加载,但是:

  • defer能够保证script加载的顺序,并且defer会在domContentLoaded事情之前执行defer中的代码;
  • asyn不能够保证script加载顺序,并且加载完后就会立即执行,不能保证在DomContentLoaded之前或者之后执行。
2.1 defer

在这里插入图片描述

  • defer不会阻塞DOM Tree的构建过程,脚本由浏览器来进行下载。脚本的执行时机是在DOMContentLoaded事件之前先执行defer中的代码。
  • defer是可以保证顺序的,也就是会按照你写的<script src=‘’ defer></script>顺序来执行
2.2 async

在这里插入图片描述

参考链接:defer 和 async

3. crossorigin

script 标签的 crossorigin 属性用于配置从第三方服务器加载脚本时的跨域行为。它有以下作用:

  1. 启用跨域资源共享(CORS)机制:

    • crossorigin 属性设置为 anonymous 时,浏览器会在请求脚本资源时在请求头中添加 Origin 字段,服务器可以根据这个字段决定是否允许跨域访问。
    • crossorigin 属性设置为 use-credentials 时,浏览器会在请求脚本资源时携带用户凭证(如 Cookies、HTTP 认证等),服务器可以根据这些信息决定是否允许跨域访问。
  2. 启用错误报告:

    • crossorigin 属性设置时,如果脚本资源加载失败,浏览器会触发 error 事件,并在控制台输出详细的错误信息。
    • 如果未设置 crossorigin 属性,则脚本资源加载失败时,浏览器不会触发 error 事件,也不会在控制台输出错误信息。

总之, crossorigin 属性可以让开发者更好地跟踪和处理跨域脚本加载的问题。这对于需要从第三方服务器加载脚本的 Web 应用程序很有帮助。

4. 外部依赖sdk.js

对于通过script标签引入进来的sdk.js,即使sdk.js内部有错误,也不会影响当前js代码的执行,这是由于浏览器内部机制做到的。但是如果调用了sdk.js里的一个方法,这个方法存在问题,那么就会影响当前脚本的执行了,因此需要try…catch…

// sdk.js
function sum(a, b) {
    c
    return a+b;
}
a
window.sum = sum;
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        哈哈哈
        <script>
            const loadScript = (url, callback) => {
                const script = document.createElement('script');
                script.type = 'text/javascript';
                script.src = url;
                const firstScript = document.querySelector('script');
                firstScript.parentNode.insertBefore(script, firstScript);
                script.onload = function () {
                    const res = sum(3, 4);
                    console.log(res)
                    console.log(22)
                    callback();
                };
            };
            loadScript('../../../public/test.js', () => {})
            console.log(333)
        </script>
    </body>
</html>

在这里插入图片描述
修改如下:

<script>
   const loadScript = (url, callback) => {
        const script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = url;
        const firstScript = document.querySelector('script');
        firstScript.parentNode.insertBefore(script, firstScript);
        script.onload = function () {
            try {
                const res = sum(3, 4);
                console.log('res', res);
            } catch (e) {
                console.log('错误', e);
            }
            console.log(22);
            callback();
        };
    };
    loadScript('../../../public/test.js', () => {});
    console.log(333);
</script>

在这里插入图片描述

5. 在HTML里通过script标签加载脚本 与 通过js创建script来加载脚本的区别

  • 如果在HTML里通过script标签加载脚本如果不写async或者defer,则为同步加载,包括下载js、执行js,是浏览器的行为。
  • 如果在js里通过document.createElement(‘script’)方式来加载脚本,则为异步,如果想为同步,则必须在onload回调触发完成。
async componentDidMount() {
    await this.loadScript(url1);
    await this.loadScript(url2);
}
componentWillUnmount() {
    this.removeScript(url1);
    this.removeScript(url2);
}

// 加载sdk
loadScript = url => new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;
    const firstScript = document.querySelector('script');
    firstScript.parentElement.insertBefore(script, firstScript);
    script.onload = resolve;
    script.onerror = reject;
});

// 移除sdk
removeScript = target => {
    const scriptArrs = Array.from(document.querySelectorAll('script'));
    let targetScript = null;
    scriptArrs.forEach(item => {
        if (item.src === target) {
            targetScript = item;
        }
    });
    if (targetScript) {
        targetScript.parentElement.removeChild(targetScript);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

. . . . .

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值