返回

JS 的线程及其任务队列:解锁运行机制的奥秘

前端

JS 的单线程特性与执行机制

JavaScript 是一种单线程脚本语言,这意味着它在同一时间只能执行一个任务。这个任务可以是函数调用、事件处理程序或任何其他类型的操作。

JavaScript 引擎使用事件循环来管理任务的执行。事件循环是一个不停运行的循环,它不断地检查是否有新的任务需要执行。如果有新任务,它就会将其添加到一个队列中。这个队列称为事件队列。

当事件队列不为空时,事件循环就会从队列中取出第一个任务并将其执行。任务执行完毕后,它就会从事件队列中删除。

同步与异步操作

在 JavaScript 中,任务可以分为两种类型:同步任务和异步任务。

同步任务是指在执行其他任务之前必须执行的任务。例如,函数调用就是一种同步任务。当您调用一个函数时,JavaScript 引擎会立即执行该函数,然后继续执行后面的任务。

异步任务是指可以稍后执行的任务。例如,setTimeout() 函数就是一个异步任务。当您调用 setTimeout() 函数时,JavaScript 引擎会将该函数添加到事件队列中,然后继续执行后面的任务。setTimeout() 函数将在指定的时间延迟后执行。

微任务与宏任务

在 JavaScript 中,任务还可以分为两种类型:微任务和宏任务。

微任务是指优先级高于宏任务的任务。微任务会在当前执行栈中的所有同步任务执行完毕后立即执行。例如,Promise.then() 就是一个微任务。

宏任务是指优先级低于微任务的任务。宏任务会在事件队列中的所有微任务执行完毕后执行。例如,setTimeout() 就是一个宏任务。

事件循环的运行机制

事件循环是一个不停运行的循环,它不断地检查是否有新的任务需要执行。如果有新任务,它就会将其添加到事件队列中。

当事件队列不为空时,事件循环就会从队列中取出第一个任务并将其执行。任务执行完毕后,它就会从事件队列中删除。

事件循环的运行机制可以表示为如下所示:

while (true) {
  // 检查事件队列中是否有微任务
  while (microTaskQueue.length > 0) {
    // 从事件队列中取出第一个微任务
    const microTask = microTaskQueue.shift();

    // 执行微任务
    microTask();
  }

  // 检查事件队列中是否有宏任务
  while (macroTaskQueue.length > 0) {
    // 从事件队列中取出第一个宏任务
    const macroTask = macroTaskQueue.shift();

    // 执行宏任务
    macroTask();
  }

  // 检查事件队列中是否有新的任务
  if (newTaskQueue.length > 0) {
    // 将新的任务添加到事件队列中
    eventQueue.push(...newTaskQueue);

    // 清空新的任务队列
    newTaskQueue = [];
  }
}

总结

JavaScript 是一种单线程脚本语言,它使用事件循环来管理任务的执行。事件循环是一个不停运行的循环,它不断地检查是否有新的任务需要执行。如果有新任务,它就会将其添加到一个队列中。这个队列称为事件队列。

当事件队列不为空时,事件循环就会从队列中取出第一个任务并将其执行。任务执行完毕后,它就会从事件队列中删除。

在 JavaScript 中,任务可以分为两种类型:同步任务和异步任务。同步任务是指在执行其他任务之前必须执行的任务。例如,函数调用就是一种同步任务。异步任务是指可以稍后执行的任务。例如,setTimeout() 函数就是一个异步任务。

在 JavaScript 中,任务还可以分为两种类型:微任务和宏任务。微任务是指优先级高于宏任务的任务。微任务会在当前执行栈中的所有同步任务执行完毕后立即执行。例如,Promise.then() 就是一个微任务。宏任务是指优先级低于微任务的任务。宏任务会在事件队列中的所有微任务执行完毕后执行。例如,setTimeout() 就是一个宏任务。