Async.js异步队列编程库基本使用介绍

JavaScript05

Async.js异步队列编程库基本使用介绍,第1张

Array | Iterable | AsyncIterable | Object的集合

需要执行的异步函数:有2种方式,普通带回调的函数,在函数之后最后必须调用回调函数传入err和result。如果err为空,则表明当前异步操作成功,将继续下一个异步执行,如果传入err不为空,则整个异步队列任务的状态即为false终止执行下面的任务。

另一种方式是es7的 async 函数,将return的值(即resolve的值)定义为此次的返回值,如果异常则自动将异常信息(即reject值)用于error信息

所有异步方法执行之后的回调函数,参数为err,results

如果方法中没有传入callback参数,则返回promise

方式一:传入callback

方式二:不传入callback,使用promise的then、catch方式

异步队列函数,同一时间并发执行的的函数的数量,仍属于异步,只不过做了每次执行的数量限制

异步串行执行,必须等到前一个异步任务状态sucess,才执行下一个任务。

按照js同步执行的顺序,函数调用会首先执行for循环,循环5次开启了5个延迟器,延时器内部的回调函数将会异步执行,会在延时1s后进入消息队列等待执行。循环了5次,所以此时i的值为5,然后同步执行console.log打印5,第一次同步执行结束,然后开始执行消息队列的异步任务,打印5个5,中间的undefined是函数调用无返回值返回的。

执行顺序和第一题相同,不同的是延时器被包裹在了一个立即执行函数内容,并把每一次循环的i作为参数传入,此时循环内部的函数形成了一个私有作用域,每一次的i变量被独立保存了起来,因此每一次循环的i的值都会被打印出来。

延时器内部回调函数是异步函数,将在延时结束后,进入消息队列等待执行,因此同步的console.log("CCCC")最优先执行,然后延时0ms的延时器的回调先进入消息队列,1000ms后第一个延时器的回调再进入消息队列等待执行,因此先执行0ms的回调打印DDDD,再执行1000ms的回调打印BBBB。

这里与上一题不同的是中间多了一个执行3s的同步while循环,因此执行顺序是这样的:

第一个延时器延时1s后内部异步回调函数进入消息队列等待执行,

等待while循环3s后打印"CCCC",

循环结束后第一个延时器内部的回调已经进入消息队列第一个执行位置等待执行。

第二个延时器延时0s后内部异步回调函数进入消息队列等待执行,延时结束后排到第一个延时器的回调函数后面,

因此异步队里内部先打印"BBBB",再打印"DDDD"

一、同步和异步

所谓单线程,无非就是同步队列和异步队列,js代码是自上向下执行的,在主线程中立即执行的就是同步任务,比如简单的逻辑操作及函数,而异步任务不会立马立马执行,会挪步放到到异步队列中,比如ajax、promise、事件、计时器等等。

也就是先执行同步,主线程结束后再按照异步的顺序再次执行。

二、时间循环(Event Loop)

Event Loop是什么?中文翻译是事件循环,等待主线程中任务全部完成后,再回来把异步队列中任务放到主程序中运行,这样反复的循环,就是事件循环。

b14d903a712b31c34f347ba7d64b697e.png

先来看组代码

console.log('开始111') setTimeout(function () {console.log('setTimeout111') }, 0) Promise.resolve().then(function () {console.log('promise111') }).then(function () {console.log('promise222') }) console.log('开始222')

打印 “开始111”,再打印“开始222”。

中途的三个异步,进入到了异步队列,等待同步执行完(打印完),返回来再执行异步,所以是后打印出来。

打印的结果先放一放,我们稍后回来再说。现在我们中途插播一段知识点:

三、宏观任务和微观任务(先执行微观任务,再执行宏观任务):

在事件循环中,每进行一次循环操作称为tick,tick 的任务处理模型是比较复杂的,里边有两个词:分别是 Macro Task (宏任务)和 Micro Task(微任务)。

简单来说:

宏观任务主要包含:setTimeout、setInterval、script(整体代码)、I/O、UI 交互事件、setImmediate(Node.js 环境)

微观任务主要包括:Promise、MutaionObserver、process.nextTick(Node.js 环境)

规范:先执行微观任务,再执行宏观任务

那么我们知道了,Promise 属于微观任务, setTimeout、setInterval 属于宏观任务,先执行微观任务,等微观任务执行完,再执行宏观任务。所以我们再看一下这个代码:

console.log('开始111') setTimeout(function () {console.log('setTimeout111') }, 0) Promise.resolve().then(function () {console.log('promise111') }).then(function () {console.log('promise222') }) console.log('开始222')

我们按照步骤来分析下:

1、遇到同步任务,直接先打印 “开始111”。

2、遇到异步 setTimeout ,先放到队列中等待执行。

3、遇到了 Promise ,放到等待队列中。

4、遇到同步任务,直接打印 “开始222”。

5、同步执行完,返回执行队列中的代码,从上往下执行,发现有宏观任务 setTimeout 和微观任务 Promise ,那么先执行微观任务,再执行宏观任务。

所以打印的顺序为:开始111 、开始222 、 promise111 、 promise222 、 setTimeout111 。

同理,我们再来分析一个代码:

console.log('开始111')setTimeout(function () { console.log('timeout111')})new Promise(resolve =>{ console.log('promise111') resolve() setTimeout(() =>console.log('timeout222'))}).then(function () { console.log('promise222')})console.log('开始222')

分析一下:

1、遇到同步代码,先打印 “开始111” 。

2、遇到setTimeout异步,放入队列,等待执行 。

3、中途遇到Promise函数,函数直接执行,打印 “promise111”。

4、遇到setTimeout ,属于异步,放入队列,等待执行。

5、遇到Promise的then等待成功返回,异步,放入队列。

6、遇到同步,打印 “开始222”。

7、执行完,返回,将异步队列中的代码,按顺序执行。有一个微观任务,then后的,所以打印 “promise222”,再执行两个宏观任务 “timeout111” “timeout222”。

所以,打印的顺序为:开始111 、 promise111 、 开始222 、 promise222 、 timeout111 、 timeout222 .

先执行主任务,把异步任务放入循环队列当中,等待主任务执行完,再执行队列中的异步任务。异步任务先执行微观任务,再执行宏观任务。一直这样循环,反复执行,就是事件循环机制。