JS 是单线程的
同步是指,任务是按照顺序依次处理的,一步步执行,当前事件没有处理完成,下一件事执行不了
异步是指,当前事件没有彻底做完,需要等待一段时间才能继续处理,此时不会等待其完成,继续执行下面任务,当后面的任务完成后,再去把没有彻底完成的事情完成
常见的异步编程:
定时器
事件绑定
AJAX 请求一般都使用异步编程处理
1. 浏览器规划同步异步机制
(1)浏览器是多线程的,JS 是单线程的(浏览器只给 JS 执行分配一个线程):单线程的特点就是一次只能处理一件事情
进程:每一个应用程序启动的时候都会开辟一个进程(浏览器打开一个页面就相当于开辟一个进程),
线程:在一个程序中(进程中),我们经常会同时干很多事情,此时我们可以分配多个线程去同时完成多项任务
(2)JS 在单线程中实现异步的机制,主要依赖于浏览器的任务队列来完成的,浏览器有两个任务队列:主任务队列、等待任务队列。
主任务队列指的是同步代码从上而下执行
等待任务队列存放的是异步代码,等待任务队列中的代码执行的前提是主任务队列中的代码执行完毕
- (3)在主任务队列自上而下执行时,遇到一个异步操作的任务,没有立即执行,而是把它放到等待任务队列中排队
- (4)当主任务队列完成后才会到等待任务中进行查找(主任务完不成,不管等待任务队列中是否有到达时间的,都不处理,继续等待主任务队列完成,因为 JS 是单线程的,一次只能处理一件事情)
- (5)等待任务队列中,谁达到条件了(如果有很多都达到条件了,先达到的先处理),就把这个任务重新放到主任务队列中去执行,把这个任务执行完,再去等待中查找
设置定时器本身是同步的,但是里面执行的代码是异步的,就诞生一个异步任务,会放到等待任务队列中。
2. 查看代码执行时间
大概计算代码执行时间的方法:
使用开始和结束的时间记录,然后相减
使用
console.time('标记')
和console.timeEnd('标记')
let startTime = new Date();
for (let i = 0; i < 9000; i++) {
}
let endTime = new Date();
console.log(new Date - startTime);
//=> 从记录标记到结束标记经历的时间
console.time('AA');
for (let i = 0; i < 90000000; i++) {
}
console.timeEnd('AA');
3. 练习
题目一:
setTimeout(() => {
console.log(1);
}, 1000);
console.log(0); // 先输出 0,再输出 1
题目二:
//=> 定时器设定一个时间,到达时间后不一定执行(如果当前还有其它同步任务正在处理,那么到时间也必须等待)
setTimeout(() => {
console.log(1);
}, 1000);
console.log(0);
while(true) {
//=> 死循环
}
//=> 只能输出 0,,不能执行定时器的事情
题目三:
//=> 先不用管异步代码,先执行同步代码,全部执行完成后再看异步的代码谁先完成,就先执行谁
setTimeout(()=>{
console.log(1);
}, 20);
console.log(2);
setTimeout(()=>{
console.log(3);
}, 10);
setTimeout(()=>{
console.log(4);
}, 100);
for (let i = 0; i < 9000; i++) {
}
console.log(5);
//=> 2 5 3 1 4
题目四:
let n = 0;
setTimeout(()=>{
console.log(++n);
}, 0); //=> 定时器时间设置为 0 也不是立即执行,每个浏览器都有一个自己最小的等待时间和反应时间(Chrome:5~6ms IE:10~13ms),所以写 0 还是异步编程
console.log(n);
//=> 0 1
题目五:
setTimeout(()=>{
console.log(1);
}, 20);
console.log(2);
setTimeout(()=>{
console.log(3);
}, 10);
console.log(4);
for (let i = 0; i < 9000; i++) {
}
console.log(5);
setTimeout(()=>{
console.log(6);
}, 8);
console.log(7);
setTimeout(()=>{
console.log(8);
}, 15);
console.log(9);
//=> Chrome: 2 4 5 7 9 6 3 8 1
//=> IE: 2 4 5 7 9 1 6 3 8