1. 进程和线程
-
一个进程中可能包含多个线程
-
进程:程序(浏览器打开一个页面,就会开辟一个进程)
-
线程:处理任务,一个线程同事只能处理一个任务
-
浏览器是多线程的
- HTTP网络线程:用于资源文件的加载
- GUI渲染线程:用于页面自上而下的渲染,最后绘制出页面
- JS渲染线程:专门用于渲染js代码
-
JS是单线程的
- 浏览器只会开辟一个线程来渲染js代码,所以js的本质都是同步的,一件一件,不能同时处理两件事
-
js中是有异步编程代码的
- 此处的异步编程不是同时处理多件事,是基于浏览器的多线程性,结合
event loop事件循环机制,构建出来的异步效果
- 此处的异步编程不是同时处理多件事,是基于浏览器的多线程性,结合
-
js中异步编程的代码
宏任务- 定时器:设置定时器是同步的,间隔时间后,触发绑定方法执行是异步的
- 事件绑定:监听事件触发
- ajax/fetch创建的网络请求,从服务器请求数据
微任务- Promise:then/resolve/reject
- async/await
// 定时器的返回值是一个数字,代表当前系统中第几个定时器,清除时候,也是基于这个数字清除
let n = 0;
let timer = setTimeout(() => {
n++;
console.log(n);
}, 1000)
console.log(timer) // 1
console.log(n) // 0
// 1 0 1
1.1 代码入队列过程
-
正常情况下,js渲染线程
-
先进行词法分析,把页面中即将要自上而下执行的代码都分析为一个个的任务,不管同步异步,放在任务队列的宏任务中
-
词法分析结束后,再从宏任务队列中,拿出来,把代码自上而下,逐一执行
-
代码执行过程中,只要创建一个异步的任务,则会把这个异步任务放到等待任务队列中
EventQueue中 -
宏任务队列按照达到条件去执行
-
微任务队列按照存放先后顺序去执行
1.2 eg
- 输出2 然后死循环
1.3 async/await
- async的作用
- 让一个函数返回一个Promise实例(默认成功状态),除非本身返回一个Promise实例,最终结果以返回的Promise实例为准
function fn() {
return 10
}
console.log(fn()) // => 10
async function fn1() {
return 10
}
console.log(fn1())
// => promise,[[PromiseState]] -> fulfilled, [[PromiseResult]] -> 10
fn1().then ...
- 函数中如果需要使用await,则必须基于async使用
- await可以把一个异步的编程模拟成同步的效果
- await后面一般会放置一个异步的Promise实例(其他值也可以)
- 会等待Promise状态为成功后,获取成功的结果,并且执行函数体中await
- 如果await后的promise是失败的,则不再处理下面的,用try catch处理
function handle() {
return new Promise(resolve=> {
setTimeout(()=> {
resolve('OK')
}, 1000)
});
}
async function fn() {
// 先执行handle,返回一个promise实例
// 等待promise变成成功态,此时await下面代码都不执行
await result = await handle();
console.log(result);
// 此处加了await,同步代码也需要等同步任务执行完再执行
// await后面的代码当作promise异步处理,状态变为成功后执行
let n = await 10;
console.log(n);
let m = await Promise.resolve('NO')
console.log(m)
// await后面实例是失败的,则不再处理之前存放的微任务,不处理失败,浏览器会抛异常
try {
let q = await Promise.reject('NO')
console.log(q)
} catch(err) {
}
}
// 输出 2 1
// fn执行遇到await,await紧跟着的立即处理,把后面代码放到微任务中,需要等promise成功后处理
async function fn() {
await 10;
console.log(1);
}
fn();
console.log(2);
1.4 一个事件完全执行完,才去下一个事件
- 一个事件中的同步,微任务执行完,才会执行下一个事件
- 2 1 4 3
1.5 eg5
1.6 eg6
- 下一个then要等上一个then的结果,task4需要等到task5返回的结果
- b f c a d