JS 单线程和事件循环
Js 是单线程,js代码从上到下依次执行,比如我们写了两个函数,肯定是上面的函数先执行,下面的函数后执行。但是这种单线程有一个非常大的问题,那就是遇到耗时的任务,后面的任务只能等待它执行完,才能进行。比如ajax 请求,它从服务器上获取数据,这本来就耗时间, 如果网络再慢,就更耗时间,那么我们只能等待返回结果,结果出来之后再向下执行,等待的过程中,用户什么都不能做,如果是在渲染阶段,也会阻止渲染UI, 用户只能看到空白页面,体验太差。
对于这种比较耗时间的任务怎么办,js 决定把它放到一边,先运行后面的任务,然后再回来处理这些耗时的任务。这就引入了异步的概念,因为我们书写代码的顺序和它执行顺序是不一致了。下面有三个函数,两个基本函数,和一个ajax 函数(作异步操作),我们的书写顺序是ajax -> add -> subtract, 但执行顺序却是 add -> sbutract -> ajax;
function add(num1,num2) {
return num1 + num2;
}
function subtract(num1,num2) {
return num2 - num1
}
function ajax() {
var url = 'http://jsonplaceholder.typicode.com/posts/1';
var xhr = new XMLHttpRequest();
xhr.open("GET",url);
xhr.onload= function () {
console.log(xhr.responseText)
}
xhr.send()
}
ajax();
console.log(add(3,5))
console.log(subtract(3,5))
这又引出了另 一个问题,异步的任务放到什么地方了?它以后回来执行,那什么时候执行?这里其实要注意一个问题,真正执行ajax操作的不是我们的js,而是浏览器,是我们的浏览器发出的http 请求。当js 执行到ajax 函数的时候,它其实是告诉浏览器去执行http 请求,然后就立即返回,执行它后面的代码,就是add 和substract 函数。那么浏览器执行完http请求,从服务器拿到了数据,怎么办?它这时执行我们的回调函数(onload 函数),就是把返回的数据传递给回调函数,然后把回调函数插入到事件(任务)队列中。js运行完add 和subtract 函数时,就没有事情可以做了,它就会去轮询事件(任务)队列,刚一轮询,它就发现,有一个onload 回调函数,那么它就会把它取出来执行这个函数。在程序运行过程中,js会一直执行轮询,直到程序结束。
Js 代码在整个程序的运行过程中分为两个部分,一种是像add 函数这种,另一种是像ajax onload 回调函数这种,相对应js 运行也分成了两个部分,一个是主线程,一个是任务(异步回调函数)队列。
js代码具体运行如下:
1, js 代码一加载进来,它就会从上到下依次执行,它也就进入一个全局执行环境,当它遇到ajax 异步操作的时候,它会告诉浏览器去执行请求,然后立即返回,执行下面的代码,遇到add函数调用,它就会进入函数执行环境,执行完add函数时,它又遇到subtract 函数,它又会进入函数执行环境。当然这里比较简单,没有嵌套函数。如果函数中还嵌套一个函数,那么它就会进入子函数的执行环境,像下图一样,这就形成了一个执行栈,上面的执行后,再执行下面的,直到全局执行环境中的代码执行完毕,执行栈为空, 这就是就是js 的主线程。

2,浏览器去执行http 请求, 在未来的一段时间内,它或者从服务器获得数据或者失败,这时它就会把我们注册的成功或失败的回调函数放入到任务(回调函数)队例中。

3, 当执行栈中的所有代码执行完毕后,就是执行栈为空时,js就会去轮询我们的任务队列(左边图片),如果有任务,它就会从任务队列的起始位置 取出第一个任务(注册的回调函数)放到执行栈去执行(右边图片),等这个回调函数执行完毕后,执行栈再为空,js再去轮询我们的任务队列,如果还有回调函数,它再取出第一个放到执行栈执行。在整个程序的执行过程中,js 会一直轮询我们的任务队列,一有任务,就会执行,这就是事件循环。


所有的程序都是栈中执行,只有执行栈空了,它有能力处理下一个任务。只要一个函数进入到执行栈,栈就不为空,栈不为空,就不能处理下一个函数,只能等到函数执行完毕。这就是所谓的 “run–to-complete ” 一次只能做一件事情。这也要求我们的回调函数中,不能执行太多任务,如果执行太多任务,栈就不为空,也就阻止了下一个任务的执行,造成阻塞。
以上所述,就是js 中的非阻塞。
JS 单线程和事件循环的更多相关文章
- JS执行机制--事件循环--笔记
JS的解析是由浏览器中的JS解析引擎完成的.JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始.但是又存在某些任务比较耗时,如IO读写等, ...
- js高级-浏览器事件循环机制Event Loop
JavaScript 是队列的形式一个个执行的 同一时间只能执行一段代码,单线程的 (队列的数据结构) 浏览器是多线程的 JavaScript执行线程负责执行js代码 UI线程负责UI展示的 Jav ...
- 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick
[摘要] 官网博文翻译,nodejs中的定时器 示例代码托管在:http://www.github.com/dashnowords/blogs 原文地址:https://nodejs.org/en/d ...
- 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick
目录 Event Loop 是什么? Event Loop 基本解释 事件循环阶段概览 事件循环细节 timers pending callbacks poll阶段 check close callb ...
- js异步、事件循环(EventLoop)小结
单线程 众所周知,JS是单线程的语言,之所以是单线程,用一句烂大街的话就是,如果两个线程同时操作一个DOM节点,那么该以哪个为准呢,虽然多线程也有办法解决,但是js毕竟是浏览器脚本语言,不需要那么复杂 ...
- 浅谈Javascript单线程和事件循环
单线程 Javascript 是单线程的,意味着不会有其他线程来竞争.为什么是单线程呢? 假设 Javascript 是多线程的,有两个线程,分别对同一个元素进行操作: function change ...
- js 队列和事件循环
1.示例代码 <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UT ...
- js event loop事件循环
浏览器环境 以下两段代码是等价的.req对事件的回调设置,实际上就是当前主线程任务队列的任务. var req = new XMLHttpRequest(); req.open('GET', url) ...
- JS高阶---事件循环模式(事件轮询)
大纲: 相关知识点: 主体: (1)模型原理 JS部分:初始化代码执行 WebAPIS:执行上下文对象(不是一个真的对象,而是一个抽象的虚拟对象,可以看做栈里的一个区域,包含很多对象) setTime ...
随机推荐
- 容器技术|Docker三剑客之docker-machine
docker-machine是什么? ocker-machine就是docker公司官方提出的,用于在各种平台上快速创建具有docker服务的虚拟机的技术,甚至可以通过指定driver来定制虚拟机的实 ...
- APM实践目录
长路漫漫,如果不能作出一款可用开源的东西出来,那是对时光的浪费. 这是我的学习分布式调用链的实践之路! 思考大纲: .Net架构篇:思考如何设计一款实用的分布式监控系统? 理论篇: http:// ...
- SpringBoot集成Apache Shiro
笔者因为项目转型的原因,对Apache Shiro安全框架做了一点研究工作,故想写点东西以便将来查阅.之所以选择Shiro也是看了很多人的推荐,号称功能丰富强大,而且易于使用.实践下来的确如大多数人所 ...
- Linux stress 命令
stress 命令主要用来模拟系统负载较高时的场景,本文介绍其基本用法.文中 demo 的演示环境为 ubuntu 18.04. 基本语法 语法格式:stress <options> 常用 ...
- centos7 关闭selinux
关闭SeLinux 临时关闭:setenforce 0 永久关闭:vi /etc/selinux/config
- c++入门之类继承初步
继承是面向对象的一种很重要的特性,先来复习基类的基本知识: 先上一段代码: # ifndef TABLE00_H # define TABLE00_H # include "string&q ...
- c++入门之类——进一步剖析
通常的,关于一个类,包含了下面几个方面: 1 声明类成员和接口:2 定义类接口函数(方法)3通过接口调用类 下面先给出第一条:声明类成员和接口 # ifndef MYTIME0_H_ # defin ...
- 1171: lfx捧杯稳啦!
escription Lfx在复习离散的时候突然想到了一个算法题,毕竟是lfx, 算法题如下: 他想知道这样的问题,先定义1~n中即是3的倍数,又是11的倍数的那些数的和sum, 他想知道sum有多少 ...
- openstack-云计算概述
一.云计算 1.云计算解决的问题 备机准备(低配) 故障恢复 安装系统 硬件资源浪费 电力资源浪费 2.云计算概念 (1)维基百科 云计算是一种通过因特网以服务的方式提供动态可伸缩的虚拟化的资源的计算 ...
- 多线程系列之九:Worker Thread模式
一,Worker Thread模式 也叫ThreadPool(线程池模式) 二,示例程序 情景:一个工作车间有多个工人处理请求,客户可以向车间添加请求.请求类:Request定义了请求的信息和处理该请 ...