美文网首页
JS三座大山之异步和单线程

JS三座大山之异步和单线程

作者: 我向你奔 | 来源:发表于2018-02-25 11:39 被阅读166次

什么是异步?

我们通过代码来感受一下异步是什么

        console.log("start");
        setTimeout(function () {
            console.log("setTimeout");
        }, 1000);
        console.log("end");

在不了解异步的情况下,可能会认为打印的顺序就是start,setTimeout,end。但事实上呢?


QQ图片20180223203539.png

此时结果并不是我们想的那样,而是按照start,end,setTimeout的顺序打印,仔细想想会发现这种打印方式不会阻塞,如果按照start,setTimeout,end的顺序执行就会在打印完start后等待一秒钟再执行setTimeout,end,在此期间程序就会被阻塞。我们再看一段代码对比一下异步和同步的区别

        console.log("100");
        alert("200")
        console.log("300");
QQ图片20180223205817.png
QQ图片20180223205851.png

现在的代码就成了你什么时候点击确定按钮,什么时候才会执行下面的代码。此时我们就可以看出同步和异步的区别了:
同步会阻塞线程,后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的;异步是异步代码会被放入一个任务队列,等到所有其他代码执行后才进行,而不会阻塞线程。

何时需要异步?

在可能发生等待的情况,在等待时我们不能什么都不做,就像alert一样阻塞程序进行,因此,所有的“需要等待的情况”都需要异步。
那什么时候需要等待?
① 定时任务:setTimeout,setInterval
② 网络请求:Ajax请求,动态<img>加载
③ 事件绑定
我们先来看一个Ajax请求的例子

       console.log("start");
       $.ajax({
           type: "GET",
           url: 'data.json', 
           dataType: "json",
           success: function (data) {
               console.log(data);
           }
       })
       console.log("end");
QQ图片20180224004605.png

<img>加载示例

console.log("start");
var img = document.createElement("img");
img.onload = function () {
      console.log("loaded")
}
img.src = "01.jpg";
console.log("end");

事件绑定示例

console.log("start");
document.getElementById("btn1").addEventListener("click", function () {
      alert("clicked");
})
console.log("end");
QQ图片20180224153345.png
QQ图片20180224153403.png

为什么会产生异步?

因为js语言的特点是单线程,也就是说,同一个时间只能做一件事,得按顺序一个一个来。我们用之前例子再来看看

console.log("100");
setTimeout(function () {
      console.log("200");
});
console.log("300");

分析一下执行步骤:① 执行第一行,打印100;② 执行setTimeout后,传入setTimeout的函数会被暂存起来,不会立即执行(单线程的特点:不能同时干两件事);③ 执行最后一行,打印300;④ 待所有程序执行完,处于空闲状态时,会立马看有没有暂存起来的要执行的;⑤ 发现暂存的setTimeout函数无需等待时间,于是立即执行。

总结一下:
同步和异步的区别:同步会阻塞代码,异步不会;例子就是alert和setTimeout,alert是同步,setTimeout是异步。
前端使用异步的情景:① 定时任务:setTimeout,setInterval;② 网络请求:Ajax请求,动态<img>加载;③ 事件绑定

为什么JS引擎是单线程

JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?所以,为了避免复杂性,从一诞生,JavaScript就是单线程。

为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

任务队列

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。

如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。

JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。

于是,所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

"任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,"任务队列"上第一位的事件就自动进入主线程。但是,由于存在后文提到的"定时器"功能,主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。

异步执行

具体来说,异步执行的运行机制如下。(同步执行也是如此,因为它可以被视为没有异步任务的异步执行。)

(1)所有同步任务都在主线程上执行,形成一个执行栈。
(2)主线程之外,还存在一个"任务队列"(task queue),只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。

只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会不断重复。
主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。

相关文章

  • 4.异步和单线程

    js的三座大山 1.原型和原型链2.作用域和闭包3.异步和单线程+变量的类型和计算+后边的知识 1.同步和异步的区...

  • js基础

    js三座大山:原型和原型链 作用域和闭包 异步和单线程引用类型:对象 数组 函数 因为指针引用的是一个空间 所以叫...

  • 彻底理清JavaScript的单线程,异步,Event Loop

    JavaScript的三座大山:单线程与异步,原型与原型链(继承),作用域和闭包。接下来就其中的单线程与异步,和延...

  • 前端JS基础一(基础知识)

    基础知识 js基础三座大山 原型 原型链 作用域 闭包 异步 单线程 知识点 1.变量类型:值类型和引用类型(指针...

  • js的单线程和异步

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

  • JS三座大山之异步和单线程

    什么是异步? 我们通过代码来感受一下异步是什么 在不了解异步的情况下,可能会认为打印的顺序就是start,setT...

  • 前端面试送命题-JS三座大山

    本篇文章比较适合3年以上的前端工作者,JS三座大山分别指:原型与原型链,作用域及闭包,异步和单线程。本文的作者是「...

  • JS执行机制

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

  • Promise入门详解和基本用法

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

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

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

网友评论

      本文标题:JS三座大山之异步和单线程

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