首页 前端知识 js文件同步和异步的引入问题

js文件同步和异步的引入问题

2024-08-04 22:08:44 前端知识 前端哥 264 598 我要收藏

文章目录

  • 同步加载和异步加载
  • JS模块的加载方法
    • CommonJS
    • ES6
    • ES6的`<script>`标签的加载方式

同步加载和异步加载

  • 同步加载:同步加载是指在主线程上按顺序执行代码,当遇到加载资源(例如网络请求、读取文件)时,主线程会停止执行后续的代码,等待资源加载完成后再接着执行后续的代码。这样的方式可能会导致用户体验不佳,因为当资源加载耗时长时,用户需要等待较长时间才能看到后续的处理结果。
  • 异步加载:异步加载则不会阻塞主线程,它会在后台加载资源,同时主线程还会继续执行后续的代码。当资源加载完成后,通常通过回调函数或者Promise(.then方法)来获取资源,并对其进行处理。这样的方式可以避免阻塞主线程,提升用户体验。

异步加载就是多个资源同时加载,同步加载就是同一时刻只加载一个资源。
JavaScript中,由于它的单线程特性,通常推荐使用异步加载的方式来处理网络请求、文件操作等耗时操作。

JS模块的加载方法

CommonJS

使用CommonJS规范require()函数加载模块是同步的,也就是说在加载完模块之前,后续代码不会执行。这在服务器端环境中非常有用,因为模块文件通常都已经在本地,加载很快,而且一般需要在服务器启动时加载所有必要的模块。

ES6

ES6的模块既可以使用同步加载也可以使用异步加载,取决import的使用方式:

  • 同步加载:同步加载是使用import的静态导入方式,结合from使用 :
    静态加载没有返回值,静态加载是一个语句,

    import module from 'module-name';
    

    在module模块加载完成之前是不会执行下面的代码的,所以在模块导入后的所有地方都可以直接使用该模块。

  • 异步加载:异步加载是使用import的动态导入方式,模块作为import的参数使用(可以是路径名也可以是模块名):
    动态加载的返回值是一个Promise对象,所以可以直接使用.then函数编写回调函数

    import('module-name').then((module) => {
      // 你可以在这里使用模块
    });
    

    也可以使用async/await语法,

    async function loadModule() {
      try {
        const module = await import('module-name');
        // 使用这个模块
      } catch (error) {
        // 处理加载错误
      }
    }
    

ES6的<script>标签的加载方式

  • <script >导入 —— 同步加载
    <script src="">标签并不是使用模块化的导入导出方式,可以使用该标签加载执行JS文件,但是其中所有的变量和函数都会在全局作用域中。
    <script src="">的导入方式是同步导入。当解析到<script src=“”>的时候会暂停解析HTML,去下载javascript文件,等文件下载完成之后再继续解析剩余的HTML文件。

  • <scrtpt type="module">导入 —— 异步加载
    使用这种方式导入的文件是异步导入,使用<scrtpt type="module">导入的时候浏览器会采用严格模式,并且模块会自动地被异步加载

    <script type="module">
      import {foo} from './foo.js';
      foo();
    </script>
    

    或者使用src导入文件:

    <script type="module" src="./main.js"></script>
    

    main.js

    import {foo} from './foo.js';
    foo();
    
  • <script src=“”>的异步加载
    可以在<script>标签中添加asyncdefer属性来使文件异步加载。

    • async 属性:这会使得浏览器非阻塞(异步)地下载 JavaScript 文件,但是一旦文件下载完成,浏览器会立刻解析并执行这个文件,这导致了 HTML 的解析可能会被暂时阻塞。多个包含 async 属性的 <script> 标签,它们的执行顺序无法保证,完全由加载完成的时间顺序决定。

    • defer 属性:这也会使得浏览器非阻塞(异步)地下载 JavaScript 文件,但是与 async 不同的是,包含 defer 属性的 <script> 标签会在整个 HTML 文档解析完成之后才开始执行。如果有多个包含 defer 属性的 <script> 标签,它们的执行顺序会按照在 HTML 文件中的出现顺序来执行。

  • <script>标签异步引入的时候如何判断模块加载完成
    使用<script src="">标签的异步引入,不像直接在js模块中的异步引入可以使用回调函数和Promise来编写异步模块加载完成之后的逻辑,但是我们有其他的解决办法:

    • 使用事件监听器

      <script>
      document.querySelector('script[src="script.js"]').addEventListener('load', function() {
        // script.js文件加载完成之后执行的逻辑代码
      });
      </script>
      <script async src="script.js"></script>
      
    • 使用onload事件监听

      <script type="module" src="./main.js" onload="init()"></script>
      <script>
        function init() {
          // main.js 已加载完毕,你可以在这里使用它导出的函数和变量
        }
      </script>
      
    • 如果被异步加载的文件可以手动编写,可以使用设置全局回调函数的方式:

      <script>
      window.scriptLoaded = function() {
        //  script.js文件加载完成之后执行的逻辑代码
      };
      </script>
      <script async src="script.js"></script>
      

      然后在 script.js 中的最后一行调用 scriptLoaded 函数:

      // script.js文件的逻辑代码
      window.scriptLoaded();
      
    • 如果是<script type="module">逻辑代码</script>的方式,可以直接使用动态import的特性

      <script type="module">
      import('script.js').then((module) => {
        //  script.js文件加载完成之后执行的逻辑代码
      });
      </script>
      
转载请注明出处或者链接地址:https://www.qianduange.cn//article/14768.html
标签
评论
发布的文章

RapidJSON介绍

2024-08-14 00:08:38

jQuery 4 beta 震撼发布

2024-08-14 00:08:36

cJSON的使用

2024-08-14 00:08:36

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!