异步方案研究小结

同步任务与异步任务

同步任务:在主线程上排队执行的任务,按序执行调用,比如渲染页面的元素
异步任务:不仅如此主线程,而是进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行,比如某一张图片的加载,某一段音乐的加载

异步的执行方式

JS在处理任务的时候,可以分为同步任务和异步任务。只有当同步任务都执行完毕之后,才会到任务队列里面执行异步任务。
执行流程

异步任务执行的顺序是按事件循环的结果,执行的方式是回调函数

回调函数

一个异步任务被添加到任务队列中,等到异步操作完成后,就会在任务队列中添加一个事件,表示异步任务完成准备,可以进入执行栈,等主线程有空时,就会读取任务队列,执行里面的任务,如果该任务指定了回调函数,那么主线程在处理该事件时,就会执行回调函数中的代码,即执行异步任务。

事件循环

在任务队列中,也分为宏任务和微任务分别在宏任务队列和微任务队列,只有微任务队列中的任务全部执行完毕后,才会执行宏任务队列里面的任务。

宏任务:当前调用栈中执行的代码成为宏任务。script setTimeout, setInterval, setImmediate, I/O, UI rendering
微任务: 当前(此次事件循环中)宏任务执行完,在下一个宏任务开始之前需要执行的任务,可以理解为回调事件。process.nextTick, Promises, Object.observe, MutationObserver

每一次事件循环触发时:
先执行同步代码,
遇到异步宏任务则将异步宏任务放入宏任务队列中,
遇到异步微任务则将异步微任务放入微任务队列中,
当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,
微任务执行完毕后再将异步宏任务从队列中调入主线程执行,
一直循环直至所有任务执行完毕。
注意:当宏任务和微任务都处于 任务队列(Task Queue) 中时,微任务的优先级大于宏任务,即先将微任务执行完,再执行宏任务;

异步的其他解决方案

回调函数

在上文已经提到过,不多赘述。他的优点是简单、易读、易实现,缺点是增加了维护的成本,提高了各部分的耦合度,让结构变得混乱,流程难以追踪(特别是出现回调嵌套的情况)。并且每个任务只能指定一个回调函数,不能用trycatch捕获异常。

事件监听

异步任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
通用性的事件监听方法:

  • 绑定HTML元素属性
  • 绑定DOM对象属性:document.getElementById(“xxx”).οnclick=test;
    在DOM2级之后,事件监听函数为addEventListener,有三个参数:
    第一个参数:事件的类型(DOM0绑定事件是直接写onclick,DOM2绑定事件的时候,要省略on)
    第二个参数:绑定的监听者(个人理解就是回调函数=>也就是点击时要执行的函数)
    第三个参数:是一个boolean类型的值(true:表示方法在捕获阶段时执行;false:表示在冒泡传播阶段执行)

发布订阅

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

Generators/yield

Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同,最大的特点就是可以控制函数的执行。语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态,还是一个遍历器对象生成函数。
可暂停函数, yield可暂停,next方法可启动,每次返回的是yield后的表达式结果。
yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。

Promise

Promise是承诺的意思,承诺它过一段时间会给你一个结果。
它是一种解决异步编程的方案。
从语法上讲,promise是一个对象,从它可以获取异步操作的消息;
promise有三种状态:
pending 初始状态也叫等待状态
fulfiled成功状态
rejected失败状态
状态一旦改变,就不会再变。创造promise实例后,它会立即执行。

主要特点

  1. Promise对象的状态不受外界影响
  2. Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆。

缺点

  1. 无法取消Promise,一旦新建它就会立即执行,无法中途取消
  2. 如果不设置回调函数,Promise内部抛出的错误,不会反映到外部
  3. 当处于pending(等待)状态时,无法得知目前进展到哪一个阶段,是刚刚开始还是即将完成

应用场景

  1. 回调嵌套
  2. 多并发请求,获取并发请求的数据

常用API

  • Promise.resolve() 默认产生一个成功的 promise。

  • Promise.reject() 默认产生一个失败的 promise,Promise.reject 是直接将值变成错误结果。

  • Promise.prototype.catch() 用来捕获 promise 的异常,就相当于一个没有成功的 then

  • Promise.prototype.finally() 如果返回一个 promise ,会等待这个 promise 也执行完毕。如果返回的是成功的 promise,会采用上一次的结果;如果返回的是失败的 promise,会用这个失败的结果,传到 catch 中。

  • Promise.all() 用来解决并发问题,多个异步并发获取最终的结果(如果有一个失败则失败)。

  • Promise.race() 用来处理多个请求,采用最快的(谁先完成用谁的)。

async/await

用同步的方式,编写异步。
async/await是基于Promise和Generators实现的,它不能用于普通的回调函数。
async和await 就是 Generators和 Promise的组合语法糖,将 generator 的 * 换成async,将 yield 换成await。

用法细节

  1. 函数前必须加一个 async,异步操作方法前加一个 await 关键字
  2. await 只能在 async 函数中运行,否则会报错
  3. Promise 如果返回的是一个错误的结果,如果没有做异常处理,就会报错,所以用 try..catch 捕获一下异常就可以了。
  4. await后面是一个pormise或者async函数会造成异步函数停止执行并且等待 promise 的解决,
  5. await后面是 正常的表达式则立即执行。

应用场景

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

推荐阅读更多精彩内容