JavaScript 事件循环完全教程

第一章:事件循环基础

1.1 什么是事件循环

JavaScript 是单线程语言,事件循环是其实现异步编程的核心机制。

练习 1.1:基本事件循环示例

展示事件循环的基本工作原理。

基本事件循环示例
console.log('1');

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

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

console.log('4');

// 输出顺序:
// 1
// 4
// 3
// 2

1.2 事件循环的组成部分

事件循环由以下几个主要部分组成:

练习 1.2:事件循环组成部分示例

展示事件循环各组成部分的交互。

事件循环组成部分示例
// 调用栈示例
function first() {
  console.log('first');
  second();
}

function second() {
  console.log('second');
}

first();

// 任务队列示例
setTimeout(() => {
  console.log('setTimeout');
}, 0);

// 微任务队列示例
Promise.resolve().then(() => {
  console.log('Promise');
});

// 输出顺序:
// first
// second
// Promise
// setTimeout

第二章:宏任务和微任务

2.1 宏任务

宏任务包括:script、setTimeout、setInterval、I/O、UI渲染等。

练习 2.1:宏任务示例

展示宏任务的执行顺序。

宏任务示例
console.log('script start');

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

setInterval(() => {
  console.log('setInterval');
}, 1000);

console.log('script end');

// 输出顺序:
// script start
// script end
// setTimeout
// setInterval (每秒执行一次)

2.2 微任务

微任务包括:Promise、MutationObserver、process.nextTick等。

练习 2.2:微任务示例

展示微任务的执行顺序。

微任务示例
console.log('script start');

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

console.log('script end');

// 输出顺序:
// script start
// script end
// Promise 1
// Promise 2

第三章:事件循环执行顺序

3.1 执行顺序规则

事件循环的执行顺序遵循以下规则:

  1. 执行同步代码
  2. 执行微任务队列中的所有任务
  3. 执行宏任务队列中的一个任务
  4. 重复步骤2和3

练习 3.1:执行顺序示例

展示事件循环的执行顺序。

执行顺序示例
console.log('1');

setTimeout(() => {
  console.log('2');
  Promise.resolve().then(() => {
    console.log('3');
  });
}, 0);

Promise.resolve().then(() => {
  console.log('4');
  setTimeout(() => {
    console.log('5');
  }, 0);
});

console.log('6');

// 输出顺序:
// 1
// 6
// 4
// 2
// 3
// 5

3.2 嵌套任务

展示嵌套的宏任务和微任务的执行顺序。

练习 3.2:嵌套任务示例

展示嵌套任务的执行顺序。

嵌套任务示例
console.log('1');

setTimeout(() => {
  console.log('2');
  Promise.resolve().then(() => {
    console.log('3');
    setTimeout(() => {
      console.log('4');
    }, 0);
  });
}, 0);

Promise.resolve().then(() => {
  console.log('5');
  setTimeout(() => {
    console.log('6');
    Promise.resolve().then(() => {
      console.log('7');
    });
  }, 0);
});

console.log('8');

// 输出顺序:
// 1
// 8
// 5
// 2
// 3
// 6
// 7
// 4

第四章:实际应用

4.1 异步编程

使用事件循环进行异步编程。

练习 4.1:异步编程示例

展示异步编程的实际应用。

异步编程示例
// 使用 Promise 处理异步操作
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data fetched');
    }, 1000);
  });
}

console.log('Start');

fetchData()
  .then(data => {
    console.log(data);
    return 'Processed ' + data;
  })
  .then(processedData => {
    console.log(processedData);
  })
  .catch(error => {
    console.error('Error:', error);
  });

console.log('End');

// 输出顺序:
// Start
// End
// Data fetched
// Processed Data fetched

4.2 性能优化

利用事件循环进行性能优化。

练习 4.2:性能优化示例

展示性能优化的实际应用。

性能优化示例
// 使用 requestAnimationFrame 优化动画
function animate() {
  const element = document.getElementById('box');
  let position = 0;
  
  function step() {
    position += 1;
    element.style.left = position + 'px';
    
    if (position < 100) {
      requestAnimationFrame(step);
    }
  }
  
  requestAnimationFrame(step);
}

// 使用 setTimeout 实现节流
function throttle(func, limit) {
  let inThrottle;
  return function() {
    const args = arguments;
    const context = this;
    if (!inThrottle) {
      func.apply(context, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

// 使用示例
const throttledScroll = throttle(() => {
  console.log('Scroll event');
}, 1000);

window.addEventListener('scroll', throttledScroll);

学习建议

建议按照章节顺序学习,每完成一个练习后再进行下一个。可以通过实际项目来实践所学知识,特别是异步编程和性能优化部分。