首先我们先看看同步与异步的定义,及浏览器的执行机制,方便我们更好地理解同步异步编程。
  
  浏览器是多线程的,JS是单线程的(浏览器只分配一个线程来执行JS)
 
  进程大线程小:一个进程中包含多个线程,例如在浏览器中打开一个HTML页面就占用了一个进程,加载页面的时候,浏览器分配一个线程去计算DOM树,分配其它的线程去加载对应的资源文件...再分配一个线程去自上而下执行JS

  同步:在一个线程上(主栈/主任务队列)同一个时间只能做一件事情,当前事情完成才能进行下一个事情(先把一个任务进栈执行,执行完成,在把下一个任务进栈,上一个任务出栈...)

  异步:在主栈中执行一个任务,但是发现这个任务是一个异步的操作,我们会把它移除主栈,放到等待任务队列中(此时浏览器会分配其它线程监听异步任务是否到达指定的执行时间),如果主栈执行完成,监听者会把到达时间的异步任务重新放到主栈中执行...
    
  [宏任务:macro task]
        - 定时器
        - 事件绑定
        - ajax
        - 回调函数
        - Node中fs可以进行异步的I/O操作
  [微任务:micro task]
        - Promise(async/await)  => Promise并不是完全的同步,当在Excutor中执行resolve或者reject的时候,此时是异步操作,会先执行then/catch等,当主栈完成后,才会再去调用resolve/reject把存放的方法执行
        - process.nextTick (node中实现的api,把当前任务放到主栈最后执行,当主栈执行完,先执行nextTick,再到等待队列中找)
   - MutationObserver   (创建并返回一个新的 MutationObserver 它会在指定的DOM发生变化时被调用。)
 

  执行顺序优先级:SYNC => MICRO => MACRO

  所有JS中的异步编程仅仅是根据某些机制来管控任务的执行顺序,不存在同时执行两个任务这一说法

先来看一个例子:

setTimeout(() => {
console.log(1);
}, 20); setTimeout(() => {
console.log(2);
}, 0);//=>默认会有最小的等待时间(V8一般是5~6MS) console.time('WHILE');
let i = 0;
while (i <= 99999999) {
i++;
}
console.timeEnd('WHILE'); setTimeout(() => {
console.log(3);
}, 10); console.log(4);

结果输出如图:

我们先模拟下浏览器的程序执行过程,代码自上而下执行,碰到第一个程序,先放入主栈(主任务队列),此时浏览器发现这是一个宏任务定时器,把它移出主栈,放入等待任务队列,再继续执行下面的代码,放入主栈执行,发现第二个任务也是宏任务的定时器,放入等待队列,继续往下执行,推入主栈,同步任务,循环99999999次之后输出次数,再执行下一个程序,也移入等待队列,再执行代码,发现是同步任务,输出4,此时主栈空闲,任务队列到达时间后先进先出的原则,首先第二个任务到达时间,把它放入主栈执行,输出2,此时本因输出3,因为第三个程序是10ms到达,第一个是20s到达,但是第三个程序是等待247.849853515625ms后才放入的等待队列,所以第一个程序先到达,输出1,最后输出3。

我们用ajax来看看js的同步与异步的执行顺序和机制,AJAX任务开始:SEND,AJAX任务结束:状态为4
let xhr = new XMLHttpRequest();
xhr.open('GET', 'xxx.txt', false);
// 放到等待区的时候,此时状态是1
xhr.onreadystatechange = () => {
console.log(xhr.readyState);//=>4
};
xhr.send();
// 同步ajax,xhr.send时为同步,xhr.send()执行完后状态为4,任务状态为4的时候主栈空闲,onreadystatechange监听到状态变化,输出4
 let xhr = new XMLHttpRequest();
xhr.open('GET', 'xxx.txt', false);
xhr.send();
// 状态已经为4了
xhr.onreadystatechange = () => {//=>状态改变才会触发,放到等待区的时候状态已经为4了,不会在改变了,所以不会执行这个方法(啥都不会输出)
console.log(xhr.readyState);
};
 let xhr = new XMLHttpRequest();
xhr.open('GET', 'xxx.txt');
xhr.send();//=>异步操作:执行SEND后,有一个线程是去请求数据,主栈会空闲下来
// 放等待区之前状态是1
xhr.onreadystatechange = () => {
console.log(xhr.readyState);//=> 2 3 4
};
// 主栈又空闲了
// 状态为2 把函数执行
// 状态为3 把函数执行
// 状态为4 把函数执行

JS中的同步异步编程的更多相关文章

  1. JS中的同步异步问题

    <script> /* * JS 是单线程 * 同步 异步 * 常见的异步 * 1.定时器 * 2.事件绑定 * 3.ajax请求(一般的都是异步) * 4.回调函数也可以理解成 异步 * ...

  2. 关于js中的同步和异步

    最近看到前端面试问到js中的同步和异步,这个问题该怎么回答? 梳理一下,js对于异步的处理,很多人的第一反应是ajax,这只能说是对了一半. 1.个人觉得,js中,最基础的异步是setTimeout和 ...

  3. .Net Core WebAPI 基于Task的同步&异步编程快速入门

    .Net Core WebAPI 基于Task的同步&异步编程快速入门 Task.Result async & await 总结 并行任务(Task)以及基于Task的异步编程(asy ...

  4. socket网络编程中的同步,异步,阻塞式,非阻塞式,有何联系与区别?

    一.举个打电话的例子: 阻塞   block   是指,你拨通某人的电话,但是此人不在,于是你拿着电话等他回来,其间不能再用电话.同步大概和阻塞差不多. 非阻塞   nonblock   是指,你拨通 ...

  5. js中的同步与异步的问题

    前言 近来,总是忙于拿js写一些案例,因为是小白,并没有什么丰富的经验,对各个知识点把握也不是很全面,写起来真的是...一言难尽,太痛苦了= =.尤其是在写一些轮播的时候,里面需要用到定时器,而一旦用 ...

  6. c#中的Task异步编程

    https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/index翻译 1. 引入 Task异步 ...

  7. I/O中的 同步异步,阻塞非阻塞

    I/O中的同步和异步的概念和线程中不太一样. I/O写的时候,默认是写到页高速缓存就返回的,然后异步刷到磁盘上.而同步的I/O指的是改动写到磁盘上之后才会返回结果.可以通过fsync(),和fdata ...

  8. js中的同步与异步

    同步:提交后等待服务器的响应,接收服务器返回的数据后再执行下面的代码    异步:与上面相反,提交后继续执行下面的代码,而在后台继续监听,服务器响应后有程序做相应处理,异步的操作好处是不必等待服务器而 ...

  9. JS中的同步和异步

    javascript语言是一门“单线程”的语言,不像java语言,类继承Thread再来个thread.start就可以开辟一个线程,所以,javascript就像一条流水线,仅仅是一条流水线而已,要 ...

随机推荐

  1. python实现人工智能Ai抠图功能

    这篇文章主要介绍了python实现人工智能Ai抠图功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 自己是个PS小白,没办法只能通过技术来证明自己. 话不多说, ...

  2. Logstash 安装及简单实用(同步MySql数据到Elasticsearch)(Linux)

    1.下载logstash wget https://artifacts.elastic.co/downloads/logstash/logstash-6.6.0.tar.gz 2. 解压logstas ...

  3. 使用asp.net core 3.0 搭建智能小车1

    跟随.net core 3.0 一起发布的System.Device.Gpio 1.0已经可以让我们用熟悉的C#原汁原味的开发莓派上面的GPIO了.并且在 Iot.Device.Bindings这个包 ...

  4. Python 图形验证码库、二维码库的使用

    1. 图形验证码库 captcha # 引入图形库 from captcha.image import ImageCaptcha # 获取图像对象 image = ImageCaptcha(width ...

  5. 《Effective Java》 读书笔记(六)避免创建不必要的对象

    java 有很多修饰类的属性的关键字:常用的static,final 说说final和static吧,平时在编程的时候,这两个关键字很多时候都觉得可有可无,最多的时候就是他们俩同时出现----定义常量 ...

  6. 学习笔记24_MVC前后台数据交互

    *最普通的交互方式,在Contoller中的Action方法内 public ActionResult Index() { ViewData["Key"] =Value; Retu ...

  7. (七)golang-变量之基本数据类型(看这篇就够了)

    1.整数类型 类型 有无符号 占用存储空间 表示范围 备注 int8 有 1字节 -2**7~2**7-1   int16 有 2字节 -2**15~2**15-1   int32 有 4字节 -2* ...

  8. JavaSE语法

    二.JavaSE语法(上) 1.Java 有没有 goto 语句? goto 是 Java 中的保留字,在目前版本的 Java 中没有使用.根据 James Gosling(Java 之父)编写的&l ...

  9. vue学习之插槽

    插槽 插槽(Slot)是Vue提出来的一个概念,正如名字一样,插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性. 个人理解:我感觉插槽就是父组件控制插槽 ...

  10. TCP/IP协议指南

    分组: packet 通常用来表示任何类型的报文. 数据报: datagram 表示网络分层技术,它也经常用于表示在OSI参考模型较高层上的发送报文. 帧: frame 特别常见用于数据链路层上的报文 ...