1.关于javaScript的单线程:
应用场景决定了javascript的单线程的特性,假如javascript是多线程,同时进行:一个线程对某一个dom进行添加属性操作,另一个线程对该线程进行删除操作,那么浏览器该听哪一个。这就决定javascript必须是单线程。
web worker:是一个多线程。它出现的目的是当浏览器有大量密集的计算时候或者响应时间很长的运算时候,页面出现卡顿,可以起一个worker子线程,主线程和worker线程互不干预,这样页面就可以进行点击之类的操作,但这个子线程不能操作DOM元素。
2.javascript事件循环:
同步任务:直接通过主线程执行,如script代码
异步任务: 进入Event Table,并注册回调函数——> Event Queue,等主线程的执行栈为空时候,读取Event Queue里面的函数就,进入主线程。如setTimeout,promise.then()等;
那怎么知道主线程的执行栈为空呢,JS引擎存在monitoring process进程,它会持续检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。
let data = [];
$.ajax({
url:www.javascript.com,
data:data,
success:() => {
console.log('发送成功!');
}
})
console.log('代码执行结束');
3.setTimeout和setInterval
setTimeout(() => { a() },3000)
b(10000000)//b代表一个执行需要耗时很久的函数
有时候我们这样写:setTimeout(()=>{},0),即使主线程执行栈是空的,这个并不是立即0毫秒执行,setTimeout有最小时间间隔限制,HTML5标准为4ms,小于4ms按照4ms处理,但是每个浏览器实现的最小间隔都不同.setInterval最小时间间隔为10ms;
4.promise与process.nextTick();
宏任务:上面我们说到的script代码,setTimeout,setInterval。
微任务:promise.then(),process.nextTick();且preocess.nextTick优先级大于promise.then;
console.log('1');
setTimeout(function() {
console.log('2');
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
process.nextTick(function() {
console.log('3');
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
1
7
6
8
2
4
9
11
3
10
5
12
总结:
1.先是宏任务-->微任务-->宏任务-->微任务一直循环下去;
2.script代码为第一层宏任务,如果有setTimeout,setInterval,则他们的回调函数会成为第二层的宏任务,
3.promise.then()和process.nextTick()是微任务,在执行完该一层的宏任务后执行,且process.nextTick()优先于promise.then();