JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。
异步:在做这件事的同时,你还可以去处理其他事
他们的本质区别:这条流水线上各个流程的执行顺序不同。
同步任务
同步任务都在主线程上执行,形成一个执行栈。
异步任务
耗时的还有资源加载放到任务队列中
宏任务:setTimeout setInterval 微->宏(宏任务之前都会先检测微任务队列中有没有微任务,如果有先执行微任务) I/O
宏任务是指在主线程中执行的较大任务,通常包括以下几种:
- setTimeout(): 定时器任务。
- setInterval(): 定时重复任务。
- I/O 操作: 例如文件读取、网络请求等。
- UI 渲染: 浏览器的渲染任务。
- script 的执行: 全局代码的执行。
微任务:Promise nextTick then() Promise的构造函数是同步任务,所以Promise.resolve是同步任务先执行,然后将then加入异步队列
微任务是相对较小的异步任务,通常在当前任务执行完毕后立即执行。主要包括:
- Promise 的 then() 和 catch(): 当 Promise 状态改变时,相关的回调会被放入微任务队列。
- MutationObserver: 用于监听 DOM 变动的 API。
- queueMicrotask(): 将函数放入微任务队列。
await后面执行的都被加到了微任务队列里,后面的都是微任务
执行顺序
在 JavaScript 中,事件循环的执行顺序如下:
- 执行一个宏任务(例如执行全局代码)。
- 执行所有的微任务,直到微任务队列清空。
- 渲染 UI 更新(如果有的话)。
- 回到步骤 1,继续执行下一个宏任务。
console.log("Start"); // 宏任务
setTimeout(() => {
console.log("Timeout"); // 宏任务
}, 0);
Promise.resolve().then(() => {
console.log("Promise"); // 微任务
});
console.log("End"); // 宏任务
结果:
Start
End
Promise
Timeout
先执行执行栈中的同步任务,将异步任务放到任务队列中
一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
事件循环:
由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环( event loop) 。
就是当一段代码进入主线程,然后主线程会抽离异步任务到任务队列,主线程的同步代码执行完以后去读取异步进行操作,然后异步不断有异步,不断出异步,这就是事件循环
执行栈把异步任务外包出去(交给浏览器来处理),在任务队列看到外包做完了,再拿回来
宿主环境
在 JavaScript 中,所谓的"宿主环境"指的是 JavaScript 代码运行的环境或平台。
JavaScript 是一种脚本语言,它需要一个宿主环境来执行。常见的 JavaScript 宿主环境包括:
- 浏览器环境:
- 浏览器是最常见的 JavaScript 宿主环境。
- 浏览器提供了 DOM(文档对象模型)、BOM(浏览器对象模型)等 API,供 JavaScript 代码与浏览器交互。
- 常见的浏览器宿主环境包括 Google Chrome、Mozilla Firefox、Safari 等。
- Node.js 环境:
- Node.js 是一个基于 Chrome V8 JavaScript 引擎的 JavaScript 运行时环境。
- 它允许 JavaScript 代码在服务器端运行,并提供了文件系统、网络、数据库等 API。
- Node.js 环境使 JavaScript 可以用于后端开发、命令行工具、桌面应用程序等场景。
- 其他宿主环境:
- 除了浏览器和 Node.js,JavaScript 也可以在其他环境中运行,如:
- IoT 设备 (如 Raspberry Pi)
- Apache Cordova (用于构建跨平台移动应用程序)
- React Native (用于构建跨平台移动应用程序)
- Electron (用于构建桌面应用程序)
不同的宿主环境提供了不同的 API 和功能,这意味着同一段 JavaScript 代码在不同的宿主环境中可能会有不同的行为和结果。开发者需要了解代码将在哪种宿主环境中运行,并编写相应的代码。
总之,宿主环境是 JavaScript 代码运行的平台或环境,它决定了 JavaScript 代码可以访问和使用哪些 API 和功能。了解不同的宿主环境特性是 JavaScript 开发的重要基础。