大家都知道,js是一个单线程的语言(只有一个线程来执行js函数),所以如果某一个函数执行任务耗时比较长的话,就会造成阻塞,使得后续任务一直处于等待状态。

一、阻塞示例

        function f1(){
for (var i = ; i < ; i++) {
console.log('f1');
}
}
function f2(){
console.log('f2');
}
f1();
f2();

f1、f2依次执行,控制台打印:

二、setTimeout函数

        function f1(){
for (var i = ; i < ; i++) {
setTimeout(()=>{
console.log('f1');
},);
}
}
function f2(){
console.log('f2');
}
f1();
f2();

f1、f2依次执行,控制台打印:

看上去好像先执行了f2,后续才执行了f1,其实不然,实际上依旧是先执行f1,再执行f2,没有实现异步,f1、f2依然是同步的(不要质疑,我说的是f1,f2没有实现异步)。

首先执行f1,利用for循环开启2000个定时器;

然后执行f2,打印字符串;

时间到了,2000个定时器触发。

注意:定时器到了时间触发之后,也并不是立即执行的,这要取决于js单线程内有没有还有没有函数正在运行,我们来看一个例子:

        function f8(){
for (let i = ; i < ; i++) {
setTimeout(()=>{
console.log('f8'+i);
},);
}
}
function f9(){
for (let j = ; j < ; j++) {
console.log('f9'+j);
}
}
f8();
f9();

我们看到,定时器的时间参数值很小,50ms,依然是依次执行f8、f9;

可以看到,虽然定时器先开启,并且第一个定时器在50ms之后,理当执行,但是此时发现,f9这个函数一直在执行任务,占据了js线程,所以这些定时器任务只好乖乖地等f9的循环走完,才开始执行。

所以说js声明的所有变量/函数都是同步的(ES6的Promise实例化之后可以有一个立即执行代码块,可视为同步任务);

但是我们可以通过各种方式开启一个异步任务(例如setTimeout函数的callback,Promise对象的then(callback)回调);

三、同步队列、异步队列

因为js是单线程的,所以任务会在线程上依次逐个执行;

在主线程上的任务队列,这些任务是同步的,他们会按先后依次执行;

另外还有一种任务队列,暂且称他们为异步任务队列,顾名思义,他们是异步任务,异步任务的特点是,必须等主线程上的任务没有了之后,才依次进入主线程执行。

来个例子感受一下:

ok,根据上图,我们可以知道,上述代码中,任务建立的顺序为:

同步任务:Promise实例化、f1的第一行打印、f1的for循环开启1000个定时器、5个f2的字符串打印;

异步任务:Promise的then回调、1000个定时器回调。

再根据之前的任务执行顺序分析,先不要看下面的执行结果,在心中想一下控制台的打印结果。

关于上述所提到的同步队列和异步队列(只是一种形象的说法),详情请戳下篇博客

四、异步实现

从上面我们可以发现,setTimeout(定时器)的回调是异步任务,这些个任务是直接放到异步任务队列中等待的。

我们熟知的ajax之所以是异步,完全得益于XMLHttpRequest这个异步对象。

ES6为方便异步编程,直接提供了一个异步对象Promise,使得异步编程变得简单。

浅谈js异步的更多相关文章

  1. 浅谈JS异步轮询和单线程机制

    单线程特点执行异步操作 js是单线程语言,浏览器只分配给js一个主线程,用来执行任务(函数),但一次只能执行一个任务,这些任务就会排队形成一个任务队列排队等候执行.一般而已,相对耗时的操作是要通过异步 ...

  2. 浅谈JS异步(asychrouous)

    一.概念 (1)asychronous 异步 是JS这种单线程语言解决多任务的一种方法,将耗时的任务(io)设定为异步工作,先交给浏览器负责相关功能的线程来实现耗时的部分工作,按顺序放入任务队列中,等 ...

  3. 浅谈JS之AJAX

    0x00:什么是Ajax? Ajax是Asynchronous Javascript And Xml 的缩写(异步javascript及xml),Ajax是使用javascript在浏览器后台操作HT ...

  4. 浅谈JS中的闭包

    浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...

  5. 浅谈 js 正则字面量 与 new RegExp 执行效率

    原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...

  6. 浅谈 js 字符串之神奇的转义

    原文:浅谈 js 字符串之神奇的转义 字符串在js里是非常常用的,但是你真的了解它么?翻阅<MDN String>就可以了解它的常见用法了,开门见山的就让你了解了字符串是怎么回事. 'st ...

  7. 浅谈 js 正则之 test 方法

    原文:浅谈 js 正则之 test 方法 其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西.先来看个东西吧. var re = /\d/; console. ...

  8. 浅谈 js 数字格式类型

    原文:浅谈 js 数字格式类型 很多人也许只知道 ,123.456,0xff 之类的数字格式.其实 js 格式还有很多数字格式类型,比如 1., .1 这样的,也有 .1e2 这样的. 可能有人说这是 ...

  9. 浅谈 js 语句块与标签

    原文:浅谈 js 语句块与标签 语句块是什么?其实就是用 {} 包裹的一些js代码而已,当然语句块不能独立作用域.可以详细参见这里<MDN block> 也许很多人第一印象 {} 不是对象 ...

随机推荐

  1. 安卓Android第三方登录-QQ登录

    要实现QQ第三方登录,其实只需要一个封装类:QQLoginManager 几乎 三行代码 就实现QQ登录功能 这里先给出Github开源项目地址,项目下有详细的使用说明   下面就开始详细说一说怎么实 ...

  2. HelloWorld程序编写调试及错误解决

    HelloWorld程序编写调试及错误解决 eclipse软件编写 相较于windows内置记事本,eclipse编写程序更为简单快捷.由其生成的程序模板编写如下: package helloworl ...

  3. 三20135320赵瀚青LINUX内核分析第二周学习笔记

    赵瀚青原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.计算机的三个法宝 存储程 ...

  4. mybatis缓存有关的设置和属性

    知识点:mybatis缓存相关的设置和属性 重点:每次执行增删改操作后,一二级缓存被清空,是因为标签设置默认属性为 flushCache="true" (1) <!-- 全局 ...

  5. OnClickListener两种监听方法

    //1种:接口OnClickListener ,在onclick响应 public class MainActivity extends Activity implements OnClickList ...

  6. 编译libmemcached

    php的扩展memcache,不支持cas,所以我们要装memcached扩展,memcached扩展是基于libmemcached,所以要先安装libmemcached 一.下载软件 1.libme ...

  7. QT 样式表基础知识

    1. 何为Qt样式表2. 样式表语法基础3. 方箱模型4. 前景与背景5. 创建可缩放样式6. 控制大小7. 处理伪状态8. 使用子部件定义微观样式 8.1. 相对定位    8.2. 绝对定位 摘要 ...

  8. web.xml上下文初始化参数

    1.在web.xml文件中配置上下文参数 <!--<context-param>标签声明上下文初始化参数, --> <!-- 上下文初始化的参数可以被应用程序用所有ser ...

  9. Vue 备

    <div id="app"> <span :class='{red:addClass}'>jam</span> </div> < ...

  10. C4 文件和目录:APUE 笔记

    C4: 文件和目录 本章主要讨论stat函数及其返回信息,通过修改stat结构字段,了解文件属性. struct stat结构定义如下: struct stat { __dev_t st_dev; / ...