Promise从入门到拿Offer之async 与 await、宏队列与微队列

1、async函数

函数的返回值为promise对象,promise对象的结果由async函数执行的返回值决定。如果任何一个await语句后面的 Promise 对象变为reject状态或遇到return,那么整个async函数都会中断执行。

await 在等待 Promise 对象时会导致 async function 暂停执行, 一直到 Promise 对象决议之后才会 async function 继续执行。

2、await表达式

await右侧的表达式一般为promise对象,但也可以是其他的值;

如果表达式是promise对象,await返回的是promise成功的值;如果表达式是其他值,直接就将此值作为await的返回值。

注意:await必须写在async函数中,但async函数中可以没有await;如果await的promise失败了,就会抛出异常,需要通过try...catch捕获处理。

常见的场景:

场景1. 一个请求接着一个请求;

场景2.并发请求;

场景3.错误处理;

场景4. 超时处理;

场景5. 并发限制。

3、宏队列与微队列

JS引擎执行图

JS中包含两个不同的队列用来存储待执行的回调函数,即宏队列和微队列。

宏队列用来保存待执行的宏任务。如定时器回调、DOM事件回调、Ajax回调。

微队列用来保存待执行的微任务,比如promise回调、mutationObserver()的回调。

JS引擎执行顺序:

1)首先执行初始化的同步代码块,遇到回调函数,需保存到对应的队列中。

2)执行微队列中的微任务。在此也可能继续存在不同的回调函数,需继续存入相应的队列。

3)每次准备执行取出第一个宏任务执行前,检查微队列是否存在微任务待执行,如果存在,则先执行微任务。

示例分析:
```

1 console.log("AAAA");

2 setTimeout(() => console.log("BBBB"), 1000);

3 const start = new Date();

4 while (new Date() - start < 3000) {}

5 console.log("CCCC");

6 setTimeout(() => console.log("DDDD"), 0);

7 new Promise((resolve, reject) => {

8  console.log("EEEE");

9  foo.bar(100);

10 })

11 .then(() => console.log("FFFF"))

12 .then(() => console.log("GGGG"))

13 .catch(() => console.log("HHHH"));

14 console.log("IIII");

```

一开始代码执行,输出`AAAA`. 1

第二行代码开启一个计时器t1(一个称呼),这是一个异步任务且是宏任务,需要等到1秒后提交。

第四行是个while语句,需要等待3秒后才能执行下面的代码,这里有个问题,就是3秒后上一个计时器t1的提交时间已经过了,但是线程上的任务还没有执行结束,所以暂时不能打印结果,所以它排在宏任务的最前面了。

第五行又输出`CCCC`

第六行又开启一个计时器t2(称呼),它提交的时间是0秒(其实每个浏览器器有默认最小时间的,暂时忽略),但是之前的t1任务还没有执行,还在等待,所以t2就排在t1的后面。(t2排在t1后面的原因是while造成的)都还需要等待,因为线程上的任务还没执行完毕。

第七行`new Promise`将执行promise函数,它参数是一个回调函数,这个回调函数内的代码是同步的,它的异步核心在于resolve和reject,同时这个异步任务在任务队列中属于微任务,是优先于宏任务执行的,(不管宏任务有多急,反正我是VIP)。所以先直接打印输出同步代码`EEEE`。第九行中的代码是个不存在的对象,这个错误要抛给reject这个状态,也就是catch去处理,但是它是异步的且是微任务,只有等到线程上的任务执行完毕,立马执行它,不管宏任务(计时器,ajax等)等待多久了。

第十四行,这是线程上的最后一个任务,打印输出 `IIII`

我们先找出线程上的同步代码,将结果依次排列出来:AAAA  CCCC  EEEE IIII

然后我们再找出所有异步任务中的微任务 把结果打印出来  HHHH

最后我们再找出异步中的所有宏任务,这里t1排在前面t2排在后面(这个原因是while造成的),输出结果顺序是 BBBB DDDD

所以综上 结果是  AAAA  CCCC  EEEE  IIII  HHHH BBBB DDDD

4、JS的异步处理函数有哪些

1)Promise 对象

Promise是异步编程的一种解决方案,

优点: 相比传统回调函数和事件更加合理和优雅,Promise是链式编程(后面会详细讲述),有效的解决了令人头痛的回调地狱问题,Promise的结果有成功和失败两种状态,只有异步操作的结果,可以决定当前是哪一种状态,外界的任何操作都无法改变这个状态。

2)Generator 函数

 Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。

特征:一是,function关键字与函数名之间有一个星号;

二是,函数体内部使用yield表达式,定义不同的内部状态;

三是,通过next方法获取每段状态的返回结果。

上面分成4次执行了Gennrator函数,第一次,获取第一个yield函数的返回结果并暂停,done:false,代表函数内的状态还没有执行结束;第二次,同理;第三次,获取return的返回结果,done:true表示函数内的状态已经执行完毕;第四次,函数内已经没有可以执行的状态,所有返回undfined,同时告诉函数内的状态已经执行完毕;如果函数内没有return,在第三次时返回undfined,done:true表示函数内的状态已经执行完毕。

3)async 函数

async 函数是在ES2017 标准中引入的,async使得异步操作变得更加方便,其实他就是Generator 函数的语法糖。

 相比Generator函数,async函数有如下四点改进:

a、内置执行器: Generator 函数的执行必须靠next()进行每一次的模块执行,async自带执行器,只需要和普通函数一样调用即可执行

b、更好的语义:async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。

c、返回值是Promise: async函数的返回值是 Promise 对象,可以用then方法指定下一步的操作;而且async函数完全可以看做多个异步函数的操作,包装成的一个 Promise对象,而await命令就是内部then命令的语法糖,即Promise.all()的用法

4)回调函数   

5)事件监听

采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。

6)发布订阅模式

存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做"发布/订阅模式"(publish-subscribe pattern),又称"观察者模式"(observer pattern)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270