js线程机制的介绍和练习

给定的几行代码,我们需要知道其输出内容和顺序。JavaScript是一门单线程语言,但有其独特的线程机制

热身代码:

setTimeout(function(){
    console.log('定时器开始啦')
});
new Promise(function(resolve){
    console.log('马上执行for循环啦');
    for(var i = 0; i < 10000; i++){
        i == 99 && resolve();
    }
}).then(function(){
    console.log('执行then函数啦')
});
console.log('代码执行结束');

JavaScript事件循环

  • 同步任务 -> 主线程 -> 任务顺序执行完毕
  • 异步任务 -> Event Table -> EventQueue(并入主执行线程)

同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。 当指定的事情完成时,Event Table会将这个函数移入Event Queue。 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。 上述过程会不断重复,也就是常说的Event Loop(事件循环)。

JS引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。

定时器线程

  1. setTimeout这个函数,是经过指定时间后,把要执行的任务加入到Event Queue中,又因为是单线程任务要一个一个执行,如果前面的任务需要的时间太久,那么只能等着
  2. setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,只要主线程执行栈内的同步任务全部执行完成,栈为空就马上执行。
  3. setInterval会每隔指定的时间将注册的函数置入Event Queue,如果前面的任务耗时太久,那么同样需要等待。
  4. 对于setInterval(fn,ms)来说,我们已经知道不是每过ms秒会执行一次fn,而是每过ms秒,会有fn进入Event Queue。

一旦setInterval的回调函数fn执行时间超过了延迟时间ms,那么就完全看不出来有时间间隔了

Promise与process.nextTick(callback)

process.nextTick 指在node.js里面,事件循环的下一次循环中调用callback

除了广义的同步和异步任务,更精细的定义为:

macro-task(宏任务):包括整体代码script,setTimeout,setInterval micro-task(微任务):Promise,process.nextTick 接下来的主要介绍这两个任务的概念和线程表现:

  1. 这两种类型的任务会进入与之对应的EventQueue
  2. 事件循环的顺序,决定JS代码的执行顺序
  3. 先是进入整体代码的宏任务,开始事件循环,然后紧接着执行当前宏任务的微任务
  4. 执行完当前宏任务的微任务后 进入EventQueue里面的下一个宏任务

代码练习

我们来分析一段较复杂的代码,看看你是否真的掌握了JS的执行机制

console.log('1');
setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
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 3 5 9 11 10 12

总结:

  • JavaScript是一门单线程语言
  • Event Loop是JavaScript的执行机制
  • 针对Promise的知识,这里推荐一篇文章,非常值得一看

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序员与猫

Go Code Review Comments 译文(截止2018年7月27日)

持续更新中… 原文最新链接 https://github.com/golang/go/wiki/CodeReviewComments/5a40ba36d38...

1473
来自专栏Java帮帮-微信公众号-技术文章全总结

JavaScript RegExp 常用的手机和邮箱正则

在做前端form表单验证的时候,经常,也是必须对input做一下判断,例如邮箱了,手机了,input非空了,input只能输入数字了等等。

1071
来自专栏拂晓风起

【超精简JS模版库/前端模板库】原理简析 和 XSS防范

1543
来自专栏TungHsu

这或许是对小白最友好的python入门了吧——21,导入模块

前边我们提到了定义函数,我们也说过了,定义函数可以让下边引用函数更加方便,“下边”可能还和我们定义函数的代码不在一个文件中,这个时候我们就需要导入函数了。 我们...

3475
来自专栏企鹅FM

深入浅出Kotlin协程

协程(Coroutines)已经随着Kotlin1.3版本一起发布了1.0正式版,android平台可以使用如下方式引入:

4K8
来自专栏从流域到海域

《笨办法学Python》 第8课手记

《笨办法学Python》 第8课手记 第八课没有新内容,作者在常见问题解答里面说得很清楚,建议每一课的常见问题解答都要仔细阅读。 代码如下: formatter...

20110
来自专栏对角另一面

lodash源码分析之chunk的尺与刀

以不正义开始的事情,必须用罪恶使它巩固。 ——莎士比亚《麦克白》 最近很多事似乎印证了这句话,一句谎言最后要用一百句谎言来圆谎。 本文为读 lodash...

2290
来自专栏xingoo, 一个梦想做发明家的程序员

Java程序员的日常 —— 工作一天的收获

看题目可能是扯皮,其实还是有很多专业知识的。从最开始没有注意到设计原则,到后面的jquery实战技巧,都是今天一天碰到的问题。 每天整理一点点,每天收获一点...

2927
来自专栏GopherCoder

『Go 语言学习专栏』-- 第九期

1251
来自专栏猿人谷

linux时间相关结构体和函数整理

一、时间类型。Linux下常用的时间类型有4个:time_t,struct timeb, struct timeval,struct timespec,cloc...

2445

扫码关注云+社区

领取腾讯云代金券