进程与线程

94 阅读2分钟

进程与线程

浏览器打开一个页面就相当于开一个“进程”(程序),在程序中,我们会同时做很多事情,每一个事情都有一个“线程”去处理,所以一个进程中可能会包含多个线程!!

浏览器是多线程的:

* GUI渲染线程:渲染页面 & 绘制图形

* JS引擎线程:渲染和解析JS代码

* 事件触发线程:监听事件触发

* 定时触发器线程:给定时器计时的

* 异步HTTP请求线程:基于HTTP网络从服务器端获取资源和信息

* WebWorker

* ...

JS是单线程的(浏览器只分配一个线程“JS引擎线程”用来渲染和解析JS代码)

* + JS中的大部分操作都是“同步”

* + 有少部分操作,结合EventLoop机制,实现了“异步”处理

* 「异步宏任务:macrotask」

* + 定时器:setTimeout/setInterval

* + 事件绑定/队列

* + 数据请求:Ajax/Fetch

* + MessageChannel

* + setImmediate「NODE」

* + ...

* 「异步微任务:microtask」

* + Promise.then/catch/finally

* + async/awai

* + queueMicrotask

* + MutationObserver

* + IntersectionObserver

* + requestAnimationFrame

* + process.nextTick「NODE」

* + ...

做题秘诀

​ @1 执行循序 先处理主线任务 其次微任务 然后才是宏任务

​ @2 从上往下看碰到异步就考虑 定时器/then

  • 如果是宏任务就放到Webapi 等到时间到了或者触发了在加到Eventqueue的队列中等待主线任务空闲再执行
  • 如果是微任务比如then 如果是promise状态确定了就加到Eventqueue的队列中等待执行
  • async function a(){}
    • await a();
      • @1 先把a()函数执行
      • 把 await a()下面的代码存到Eventqueue的队列中等待执行

例题

setTimeout(() => {
    console.log(1);
}, 20);
console.log(2);
setTimeout(() => {
    console.log(3);
}, 10);
console.log(4);
for (let i = 0; i < 90000000; i++) {}
console.log(5);
setTimeout(() => {
    console.log(6);
}, 8);
console.log(7);
setTimeout(() => {
    console.log(8);
}, 15);
console.log(9);

//=>2 4 5 7 9 3 1 6 8

image-20210519142919801

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
    console.log('async2');
}
console.log('script start');
setTimeout(function() {
    console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
console.log('script end');

/*
	script start
	async1 start
	async2
	promise1
	script end
	async1 end
	promise2
	setTimeout
*/
let body = document.body;
body.addEventListener('click', function () {
    Promise.resolve().then(() => {
        console.log(1);
    });
    console.log(2);
});
body.addEventListener('click', function () {
    Promise.resolve().then(() => {
        console.log(3);
    });
    console.log(4);
});

/*
	2
	1
	4
	3
*/
console.log('start');
let intervalId;
Promise.resolve().then(() => {
    console.log('p1');
}).then(() => {
    console.log('p2');
});
setTimeout(() => {
    Promise.resolve().then(() => {
        console.log('p3');
    }).then(() => {
        console.log('p4');
    });
    intervalId = setInterval(() => {
        console.log('interval');
    }, 3000);
    console.log('timeout1');
}, 0);

/*
	start
	p1
	p2
	timeout1
	p3
	p4
	interval 循环没三秒答应1次
*/
setTimeout(() => {
    console.log('a');
});
Promise.resolve().then(() => {
    console.log('b');
}).then(() => {
    return Promise.resolve('c').then(data => {
        setTimeout(() => {
            console.log('d')
        });
        console.log('f');
        return data;
    });
}).then(data => {
    console.log(data);
});

/*
	b
	f
	c
	a
	d
*/	
function func1() {
    console.log('func1 start');
    return new Promise(resolve => {
        resolve('OK');
    });
}
function func2() {
    console.log('func2 start');
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('OK');
        }, 10);
    });
}
console.log(1);
setTimeout(async () => {
    console.log(2);
    await func1();
    console.log(3);
}, 20);
for (let i = 0; i < 90000000; i++) {} //循环大约要进行80MS左右
console.log(4);
func1().then(result => {
    console.log(5);
});
func2().then(result => {
    console.log(6);
});
setTimeout(() => {
    console.log(7);
}, 0);
console.log(8);

/*
	1
	4
	func1 start
	func2 start
	8
	5
	2
	func1 start
	3
	7
	6
*/

1.png

2.png

3.png

4.png

5.png