JavaScript中的异步,事件循环,任务队列。

1.线程

众所周知,在我们的概念中,JS是单线程多事件队列的脚本语言,但是这里的单线程只是指的是浏览器负责解析和执行JS代码只有一条线程,

但是在浏览器的渲染进程是可以提供多条线程的(也就是我们说的异步。)

JS 单线程 主线程    别人能够看到的线程         JS引擎    V8
   1. GUI线程    子线程    听从主线程管理的    别人不能够看到的    webkit
   2. 计时线程    子线程    管理两个定时器的,settimeout          setIterval
   3.事件线程    子线程    管理事件    
   3. 网络线程    子线程    管理http请求的

主线程是老大,其他的都是他的小弟!

2.事件循环(Event loop)

主线程在执行过程中遇到了异步任务,就发起函数或者称为注册函数,通过event loop线程通知相应的工作线程(如ajax,dom,setTimout等),同时主线程继续向后执行,不会等待。等到工作线程完成了任务,eventloop线程会将消息添加到消息队列中,如果此时主线程上调用栈为空就执行消息队列中排在最前面的消息,依次执行。新的消息进入队列的时候,会自动排在队列的尾端。

    

 

         如上图所言,JS主线程的函数执行,都压到任务栈中,遇到异步函数,如Promise,定时器,交给指定的子线程处理,然后继续执行同步代码,也就是主线程线得东西。异步函数在到达触发条件的时候,如定时器到时,Ajax请求响应,然后把相应的回调函数处理,然后根据异步模块的类型,将他们压入指定的任务队列,如果执行栈在把同步代码执行完成之后,里面没有东西去执行了,就从任务队列里取一个任务执行(这里一般先执行微队列里面的任务,再执行宏队列里面的任务,如此循环往复,也就形成了事件循环,即Event loop)

2.1JS中宏任务和微任务

                                                                                        

3.实例演示

上面大概讲了一下事件循环和任务队列的概念,现在我们来举几个简单的例子来更直观的说明一下什么是事件循环,什么是任务队列。

Demo01.

<script>
        setTimeout(() => {
            console.log(1);
        }, 0)
        console.log(2);
</script>

 

Demo01.在上面这个简单的例子中,如果他们都是同步代码,按照自上而下的输出的话,应该是输出1再输出2,但是里面settimeout定时器在JS中是异步的,主线程会把他扔给我们前面说的四大子线程中的计时线程去执行,当他达到触发条件后,他会被压缩到任务队列中,而且计时器是会被分为任务队列中的宏队列,等到主线程的输出2之后,才会执行宏任务队列中的任务。所以这里当然是先输出2再输出1啦!

Demo02.

<script>
        console.log(1);
        setTimeout(() => {
            console.log(2);
        }, 0)

        new Promise((res, rej) => {
            res('test')
            console.log(3);
        }).then(val => {
            console.log(4);
        })
</script>

Demo02.我们在demo1的基础上,加上了一个Promise构造函数,我们再来看看,输出的结果又要怎么分析呢。我们来看看代码,首先主线程上能执行的,console.log(1),然后定时器肯定是异步,交给异步模块处理,先跳过他。我们再往下面看,这里Promise构造函数是同步的。所以里面的内容也是主线程先执行的内容,然后再来看他的then方法是,then方法是异步的。所以先执行输出1和3。再来看异步模块。当计时器达到时间后触发被指定到宏任务队列中,而then方法再promise执行后,res回调后执行。他被放进微任务队列中。JS执行栈先执行微任务队列再执行宏任务队列。所以先输出4再输出3,所以可以看到打印出1,3,4,2啦!

在基本了解异步,事件循环和任务队列之后,我们再来看一看一道经典面试题吧!

Demo03.

<script>
        console.log(1);
        setTimeout(() => {
            console.log(2);
            Promise.resolve().then(() => {
                console.log(3);
            })
        }, 0)
        new Promise(function (res, rej) {
            console.log(4);
            setTimeout(function () {
                console.log(5);
                res(6);
                console.log(7);
            }, 0)
        }).then((res) => {
            console.log(8);
            setTimeout(() => {
                console.log(res);
            }, 0)
        });
        console.log(9);
</script>

在这里博主卖个关子,把这道题交给大家去解答,大家可以在评论区畅所欲言发表自己的看法!如果你真正的分析对了这里的输出顺序,那么我觉得那你对JS中的异步和事件循环,任务队列的运行机制也差不多基本搞清楚了!希望大家畅所欲言!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值