一、单线程模型
单线程模型指的是,JavaScript 只在一个线程上运行。也就是说,JavaScript 同时只能执行一个任务,其他任务都必须在后面排队等待
JavaScript为什么是单线程 JavaScript 之所以采用单线程,而不是多线程,跟历史有关系。JavaScript 从诞生起就是单线程,原因是不想让浏览器变得太复杂,因为多线程需要共享资源、且有可能修改彼此的运行结果,对于一种网页脚本语言来说,这就太复杂了。如果 JavaScript 同时有两个线程,一个线程在网页 DOM 节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?是不是还要有锁机制?所以,为了避免复杂性,JavaScript 一开始就是单线程,这已经成了这门语言的核心特征,将来也不会改变
1.1 事件循环
出现背景
如果排队是因为计算量大,CPU 忙不过来,倒也算了,但是很多时候 CPU 是闲着的,因为 IO 操作(输入输出)很慢(比如 Ajax 操作从网络读取数据),不得不等着结果出来,再往下执行
解决方案
JavaScript 语言的设计者意识到,这时 CPU 完全可以不管 IO 操作,挂起处于等待中的任务,先运行排在后面的任务。等到 IO 操作返回了结果,再回过头,把挂起的任务继续执行下去。这种机制就是 JavaScript 内部采用的“事件循环”机制(Event Loop)
1.2 同步任务与异步任务
程序里面所有的任务,可以分成两类:同步任务synchronous
和异步任务asynchronous
- 同步任务
- 是那些没有被引擎挂起、在主线程上排队执行的任务。只有前一个任务执行完毕,才能执行后一个任务
- 异步任务
- 是那些被引擎放在一边,不进入主线程、而进入任务队列的任务。只有引擎认为某个异步任务可以执行了(比如 Ajax 操作从服务器得到了结果),该任务(采用回调函数的形式)才会进入主线程执行。排在异步任务后面的代码,不用等待异步任务结束会马上运行,也就是说,异步任务不具有“堵塞”效应
二、任务队列与事件循环(自行搜索学习)
Call Stack
:执行栈Task Queue
:任务队列(宏任务队列/消息队列)Microtask Queue
:微任务队列Event Loop
:事件循环机制三、常见的异步任务
3.1 认识回调函数(callback)
回调函数是异步操作最基本的方法 ```javascript function f1(callback) { // … callback(); }
- 是那些被引擎放在一边,不进入主线程、而进入任务队列的任务。只有引擎认为某个异步任务可以执行了(比如 Ajax 操作从服务器得到了结果),该任务(采用回调函数的形式)才会进入主线程执行。排在异步任务后面的代码,不用等待异步任务结束会马上运行,也就是说,异步任务不具有“堵塞”效应
function f2() { // … }
f1(f2);
<a name="KAEkv"></a>
## 3.2 定时器
<a name="ZXwSX"></a>
### 3.2.1 `setTimeout()`
`setTimeout`函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器
```javascript
var timeoutID = scope.setTimeout(function[, delay, arg1, arg2, ...]);
console.log(1);
setTimeout('console.log(2)',1000);
console.log(3);
// 1
// 3
// 2
3.2.2 setInterval()
setInterval
函数的用法与setTimeout
完全一致,区别仅仅在于setInterval
指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行
var intervalID = setInterval(func, [delay, arg1, arg2, ...]);
var timer = setInterval(function() {
console.log(2);
}, 1000)
3.2.3 clearTimeout(),clearInterval()
setTimeout
和setInterval
函数,都返回一个整数值,表示计数器编号。将该整数传入clearTimeout
和clearInterval
函数,就可以取消对应的定时器
var id1 = setTimeout(f, 1000);
var id2 = setInterval(f, 1000);
clearTimeout(id1);
clearInterval(id2);
3.3 DOM事件监听
document.querySelector('button').onclick=function(event){
console.log('按钮监听到点击行为');
}
3.4 http异步请求
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
<script>
$.ajax(
url: "http://localhost:3000/posts",
type: "get",
dataType: "json",
data: { "id": 5 },
beforeSend: function(xhr) { console.log(xhr); },
success: function(data) { console.log(data); },
error: function(xhr) { console.log(xhr); },
complete: function(xhr) { console.log(xhr); }
)
</script>