美文网首页
JS运行机制(异步和单线程)

JS运行机制(异步和单线程)

作者: 陈裔松的技术博客 | 来源:发表于2018-11-29 22:35 被阅读0次

题目1

console.log(1);
setTimeout(() => {
    console.log(2);
}, 1000);
console.log(3);

// 运行结果1 3 2

分析:
这个运行结果很正常,因为2的输出要延迟一秒,所以3会先输出。

题目2

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

// 运行结果1 3 2

困惑:
这里我们设定了2的等待时间是0秒,0秒就是不需要等待。
那输出应该是1 2 3呀,为什么实际却还是1 3 2 ?

分析:
这里就引出的js运行机制的两个概念,单线程和任务队列。
JS的运行是单线程的,所谓单线程,意思是说js在一个同一时间只能做一件事情。

所谓任务队列,就是JS的执行任务,其中包含同步任务和异步任务。
在本题中,console.log(1);console.log(3);都属于同步任务,setTimeout属于异步任务。

首先,同步任务console.log(1);会直接执行。
然后,遇到下一步的异步任务setTimeout,JS会将此任务挂起(先不执行),直接往下走。
再次,同步任务console.log(3);会直接执行。
最后,所有的同步任务都处理之后,再去响应异步任务。

所以,虽然setTimeout的时间是0,但是因为它是一个异步任务,所以是最后执行的。
导致最终的运行结果是1 3 2。

知识点:
同步任务的优先级高于异步任务

题目3

console.log(1);
while(true){

}
console.log(2);

// 运行结果1

分析:
while是一个同步任务,所以会按顺序先while,在执行console.log(2);
while没有执行完之前,console.log(2);是不会执行的。

题目4

console.log(1);
setTimeout(() => {
    console.log(2);
}, 0);
while(true){

}

// 运行结果1

分析:
setTimeout是一个异步任务,在所有通过任务没有执行完之前,是不会执行的。
所以,虽然在物理上,setTimeout写在while之前,但是2也是无法输出的。

题目5

for(var i=0;i<4;i++){
    setTimeout(() => {
        console.log(i)
    }, 1000);
}

// 运行结果(4)4

困惑:
一般理解应该是0 1 2 3才对,怎么是4个4呢?

分析:

  1. 每次执行for循环的时候,由于循环体里面是一个异步任务,所有JS不会去执行它。
  2. for循环接着往下执行,直到循环结束,这时候i的值已经是4了。这个过程非常快,大概1毫秒都不到。
  3. 同步任务(也就是4个for循环体)执行完之后,会去执行异步任务。但是这个时候异步队列中是没有任务的。所以什么也不会做。
  4. 浏览器中有个时间模块,当这个时间模块检测到时间(这里就是1秒)到了,才会把异步放入异步队列中。所以1秒之后,这些异步任务开始执行。而输出的结果都是4,因为在第2步的时候,i已经变成4了。

知识点:
异步任务的放入时间:setTimeout中的时间到了才会放入。
异步任务的执行时间:所有同步任务执行完之后才会执行。

总结1:事件循环(Event Loop)

以下这张图可以解释js的运行机制,包括事件循环(Event Loop)

微信图片_20181130100409.png
  • 执行栈执行的是同步任务
  • 异步任务的放入时间:setTimeout中的时间到了才会放入。
  • 异步任务的执行时间:所有同步任务执行完之后才会执行。
  • 开启异步任务的情况:
    定时任务:setTimeout和setInterval
    网络请求:ajax请求,动态<img>加载
    事件绑定(DOM事件)
    ES6中的Promise

总结2:同步与异步的区别

  • 同步会阻塞代码的执行
console.log(100);  // 第一步:打印100
alert(200);        // 第二步:弹框显示200,等待用户点击确定按钮(alert是同步处理)
console.log(300)   // 第三步:用户点击上一步的确认按钮之后,显示300
  • 异步不会阻塞代码的执行
console.log(100);      // 第一步:打印100
setTimeout(() => {
    console.log(200);  // 第三步:1秒之后打印200
}, 1000);
console.log(300)       // 第二步:打印300

相关文章

  • 运行机制,宏任务 与 微任务

    运行机制: JS 的本质是单线程执行 事件队列:同步任务,异步任务() 运行机制 1,JS 的本质是单线程执行 单...

  • javascript异步详解1:事件循环机制EventLoop

    一. js运行机制 js是单线程,但是存在同步【阻塞】和异步【非阻塞】执行模式 同步:从上到下、从左到右的⽅式执⾏...

  • JavaScript执行机制、Event Loop

    一、运行机制 JavaScript是单线程运行机制。 为什么JavaScript是单线程?单线程就是说,js在同一...

  • js的单线程和异步

    js的单线程和异步 js是一直是单线程的,浏览器才是实现异步的那个家伙

  • JS运行机制(异步和单线程)

    题目1 分析:这个运行结果很正常,因为2的输出要延迟一秒,所以3会先输出。 题目2 困惑:这里我们设定了2的等待时...

  • 面试总结

    1、js运行机制 JS单线程运行概念:js在同一时间只能做一件事 任务队列概念: 任务顺序:同步任务-->异步...

  • JS执行机制

    首先我们来看几个问题: 1.JS是单线程的么?2.JS有异步么?3.JS单线程怎么实现的的异步 1.JS是单线程的...

  • eventloop机制 和 JavaScript 运行机制详解

    eventloop机制 和 JavaScript 运行机制详解 一、为什么Javascript是单线程 js这门语...

  • Promise入门详解和基本用法

    异步调用 异步 JavaScript的执行环境是单线程。 所谓单线程,是指JS引擎中负责解释和执行JavaScri...

  • javascript单线程,异步与执行机制

    js的单线程模型与游览器的进程/线程息息相关,在了解js单线程与异步的时候,建议先看看这篇文章 单线程/异步 js...

网友评论

      本文标题:JS运行机制(异步和单线程)

      本文链接:https://www.haomeiwen.com/subject/wkbqcqtx.html