异步性

Frontend SELF ZH
第 43 级 , 课程 0
可用

1.1 异步性的基本概念

在 JavaScript 中,异步性允许在后台执行任务,而不阻塞主执行线程。 这对于可能占用大量时间的任务特别重要,比如网络请求、文件读取和计时器。现在我们将讨论 JavaScript 中异步编程的基本概念,并举例说明其应用。

JavaScript 的单线程特性

JavaScript 是一种单线程语言:这意味着它按顺序在一个线程中执行代码。 然而,异步操作允许任务在后台执行,从而释放主线程以执行其他任务。

Event Loop (事件循环)

事件循环是一个关键机制,它允许 JavaScript 处理异步任务。 事件循环管理消息队列 (Message Queue) 和微任务队列 (Microtask Queue),确保异步操作的执行。

  1. 消息队列:包含任务,如事件处理程序、网络请求和计时器。这些队列中的任务按顺序执行。
  2. 微任务队列:包含比消息队列中的任务优先级更高的任务。示例包括 Promise 的完成和微任务中的回调函数调用。

事件循环不断检查这两个队列,并在主线程空闲时执行队列中的任务。

异步操作

异步操作允许在后台执行任务。主要的异步操作示例包括:

  • 计时器 (setTimeout, setInterval)
  • 事件处理程序
  • 网络请求 (例如, XMLHttpRequest, Fetch API)
  • 文件读写 (在 Node.js 中)

让我们来看几个异步操作的示例。

1.2 计时器

计时器允许在特定的延迟后或定期执行任务。

setTimeout 使用示例

在这个示例中,setTimeout 设置函数在 2 秒后执行。因此首先输出的是 StartEnd,然后在 2 秒后输出 Executed after 2 seconds

JavaScript
    
      console.log('Start');

      setTimeout(() => {
        console.log('Executed after 2 seconds');
      }, 2000);

      console.log('End');
    
  

setInterval 使用示例

在这个示例中,setInterval 每秒执行一次函数,增加计数器并输出其值。 当计数器达到 5 时,通过 clearInterval 清除该计时器:

JavaScript
    
      let counter = 0;

      const intervalID = setInterval(() => {
        counter++;
        console.log(`Counter: ${counter}`);
        if (counter >= 5) {
          clearInterval(intervalID);
        }
      }, 1000);
    
  

1.3 事件处理程序

事件处理程序允许响应用户操作或其他事件来执行代码。

事件处理程序使用示例

在这个示例中,click 事件处理程序被添加到按钮。当用户点击按钮时, 输出信息 Button clicked!

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Event Handler Example</title>
        </head>
        <body>
          <button id="myButton">Click me</button>

          <script>
            const button = document.getElementById('myButton');

            button.addEventListener('click', () => {
              console.log('Button clicked!');
            });
          </script>
        </body>
      </html>
    
  

1.4 网络请求

网络请求允许向服务器发送异步 HTTP 请求。

XMLHttpRequest 使用示例

在这个示例中,创建了一个异步的 GET 请求到 API,当请求完成时,响应输出到控制台:

JavaScript
    
      const xhr = new XMLHttpRequest();
      xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1', true);

      xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
          const response = JSON.parse(xhr.responseText);
          console.log(response);
        }
      };

      xhr.send();
    
  

1.5 Event Loop 的实际应用

为了更好地理解 Event Loop 的工作原理,让我们看下面的例子:

JavaScript
    
      console.log('Start');

      setTimeout(() => {
        console.log('Timeout 1');
      }, 0);

      Promise.resolve().then(() => {
        console.log('Promise 1');
      });

      setTimeout(() => {
        console.log('Timeout 2');
      }, 0);

      Promise.resolve().then(() => {
        console.log('Promise 2');
      });

      console.log('End');
    
  

预期输出如下:

  • Start
  • End
  • Promise 1
  • Promise 2
  • Timeout 1
  • Timeout 2

在这个示例中,首先执行的是同步操作 (console.log('Start')console.log('End'))。然后 执行的是微任务 (Promise 的处理程序),只有在此之后才执行消息队列中的任务 (setTimeout)。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION