异步知识点

目录

同步和异步的理解

为什么js是单线程

Promise和 async await 区别

defer和async区别

实现异步的方法

怎么解决callback多层嵌套(回调地狱)

promise相关知识点

Promise实现文件读取​编辑

用Promise实现sleep​编辑

宏微队列

任务执行顺序​编辑


同步和异步的理解

同步

  • 指在 主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务。
  • 也就是调用一旦开始,必须这个调用 返回结果(划重点——)才能继续往后执行。程序的执行顺序和任务排列顺序是一致的。

异步

  • 异步任务是指不进入主线程,而进入 任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程。
  • 每一个任务有一个或多个 回调函数。前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行。
  • 程序的执行顺序和任务的排列顺序是不一致的,异步的。
  • 我们常用的setTimeout和setInterval函数,Ajax都是异步操作。

为什么js是单线程

这主要和js的用途有关,js是作为浏览器的脚本语言,主要是实现用户与浏览器的交互,以及操作dom;这决定了它只能是单线程,否则会带来很复杂的同步问题。 举个例子:如果js被设计了多线程,如果有一个线程要修改一个dom元素,另一个线程要删除这个dom元素,此时浏览器就会一脸茫然,不知所措。所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变

<扩展>

  • 进程:是cpu分配资源的最小单位;(是能拥有资源和独立运行的最小单位)
  • 线程:是cpu调度的最小单位;(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)
  • 浏览器是多进程的:放在浏览器中,每打开一个tab页面,其实就是新开了一个进程,在这个进程中,还有ui渲染线程,js引擎线程,http请求线程等。 所以,浏览器是一个多进程的。

为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

Promise和 async await 区别

1、定义:

Promise 是异步编程的一种解决方案,比传统的解决方案:回调函数和事件,更合理和更强大,简单地说,Promise好比容器,里面存放着一些未来才会执行完毕(异步)的事件的结果,而这些结果一旦生成是无法改变的

async await也是异步编程的一种解决方案,他遵循的是Generator 函数的语法糖,他拥有内置执行器,不需要额外的调用直接会自动执行并输出结果,它返回的是一个Promise对象

2、区别:

  • Promise的出现解决了传统callback函数导致的“地域回调”问题,但它的语法导致了它向纵向发展行成了一个回调链,遇到复杂的业务场景,这样的语法显然也是不美观的。而async await代码看起来会简洁些,使得异步代码看起来像同步代码,await的本质是可以提供等同于”同步效果“的等待异步返回能力的语法糖,只有这一句代码执行完,才会执行下一句
  • async await与Promise一样,是非阻塞的。
  • async await是基于Promise实现的,可以说是改良版的Promise,它不能用于普通的回调函数。

defer和async区别

区别主要在于一个执行时间,defer会在文档解析完之后执行,并且多个defer会按照顺序执行,而async则是在js加载好之后就会执行,并且多个async,哪个加载好就执行哪个

<解析>

在没有defer或者async的情况下:会立即执行脚本,所以通常建议把script放在body最后

<script src="script.js"></script>

有async的话,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。但是多个js文件的加载顺序不会按照书写顺序进行

<script async src="script.js"></script>

有derer的话,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成,并且多个defer会按照顺序进行加载

<script defer src="script.js"></script>

实现异步的方法

回调函数(Callback)、事件监听、发布订阅、Promise/A+、生成器Generators/ yield、async/await

1、回调函数(Callback)

回调函数是异步操作最基本的方法。以下代码就是一个回调函数的例子:

但是回调函数有一个致命的弱点,就是容易写出回调地狱(Callback hell,回调函数中嵌套回调函数的情况就叫做回调地狱,回调地狱就是为是实现代码顺序执行而出现的一种操作,它会造成我们的代码可读性非常差,后期不好维护,解决回调地狱的方法:1.Promise,2.async/await。假设多个请求存在依赖性,你可能就会写出如下代码:

 回调函数的优点是简单、容易理解和实现,缺点是不利于代码的阅读和维护,各个部分之间高度耦合,使得程序结构混乱、流程难以追踪(尤其是多个回调函数嵌套的情况),而且每个任务只能指定一个回调函数。此外它不能使用 try catch 捕获错误,不能直接 return。

2、事件监听

 3、发布订阅

4、Promise/A+

5、生成器Generators/ yield

 6、async/await

怎么解决callback多层嵌套(回调地狱)

回调地狱有两种解决方案:

  1. Promises
  2. Async/await

promise相关知识点

1、语法

executor 函数在Promise构造函数执行时同步执行,被传递 resolve 和 reject 函数(executor函数在Promise构造函数返回新建对象前被调用)。
executor 内部通常会执行一些异步操作,一旦完成,可以调用resolve函数来将promise状态改成fulfilled(完成),或者将promise的状态改为rejected(失败)。
如果在executor函数中抛出一个错误,那么该promise 状态为rejectedexecutor函数的返回值被忽略。

例子:

 2、原型方法

Promise.resolve(value)

Promise.reject(reason)

Promise.prototype.then(onFulfilled, onRejected)

 Promise.prototype.catch(onRejected)

 Promise.all(iterable)

Promise.race(iterable)

Promse.race与Promise.all相反

Promise实现文件读取

用Promise实现sleep

宏微队列

JS 中用来存储待执行回调函数的队列包含 2 个不同特定的列队

  • 宏列队:用来保存待执行的宏任务(回调),比如:定时器回调、DOM 事件回调、ajax 回调
  • 微列队:用来保存待执行的微任务(回调),比如:promise的回调、MutationObserver 的回调

JS 执行时会区别这 2 个队列

  • JS 引擎首先必须先执行所有的初始化同步任务代码
  • 每次准备取出第一个宏任务执行前, 都要将所有的微任务一个一个取出来执行,也就是优先级比宏任务高,且与微任务所处的代码位置无关

任务执行顺序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值