深层理解promise与async await

一个新事物的产生一定是为了解决什么问题或者优化什么东西。我们要深层理解promise与async await 就需要回到问题最早出现的地方。

一、异步

1、为什么会产生异步?

我们都知道js是单线程的,浏览器是多进程的,但为什么这么设计呢?

首先我们先来了解一下什么是进程、线程:

进程是cpu分配资源的最小单位。线程是cpu调度的最小单位。线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程。

一个系统中,会存在很多进程,它们都会占用独立的内存。每个进程对应许多线程,它会告诉中央处理器(CPU)如何运行代码。

正因为js代码是顺序执行的,很多时候,比如网络请求数据返回时间是30s,这个时间不可能一直等待,就先跳过这个环节,向下执行,直到数据返回在执行对应代码,这就是异步。

同步会按照代码顺序执行,而异步不按照代码顺序执行,所以它执行效率更高。

2、什么时候会用到异步?

  • 定时任务:setTimeout、setInterval
  • 网络请求:ajax 请求、ajax图片加载
  • 事件监听器:addEventListener

二、异步编程 

我们针对异步操作选择了哪些方法==>

1、回调函数

其实就是函数里面调用函数,把B函数放在A函数的回调里面。

缺点:

  • 过多的回调容易形成回调地狱(最大缺点)
  • 不利于代码的阅读和维护
  • 每个任务只能指定一个回调函数
  • 不能捕获异常

2、promise

 Promise 是异步编程的一种解决方案,其实是一个构造函数,它的状态不受外界影响。

它不仅可以避免回调地狱,也能捕获异常。

存在三种状态:

pending初始状态
fulfilled意味着操作成功完成
rejected意味着操作失败

只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。一旦状态改变,就不会再变,任何时候都可以得到这个结果。

优点

1、可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数,链式操作减低了编码难度

2、提供统一的接口,使得控制异步操作更加容易

3、代码可读性明显增强

缺点

1、无法取消,一旦新建它就会立即执行,无法中途取消

2、如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部

3、当处于 Pending 状态时,无法得知目前进展到哪一个阶段

Promise 构造函数包含一个参数和一个带有 resolve(解析)和 reject(拒绝)两个参数的回调。在回调中执行一些操作(例如异步),如果一切都正常,则调用 resolve,否则调用 reject。

Promise构造函数存在以下方法:

Promise.all()

可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值,其余不会被返回。

Promse.race()

Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

Promse.allSettled()

接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例,所有的方法执行完后调用

Promse.any()有一个.then()成功执行就会调用

Promise构建出来的实例存在以下方法:

then()是实例状态发生改变时的回调函数,第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数
catch()

是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数

finally()

用于指定不管 Promise 对象最后状态如何,都会执行的操作

3、Generator 函数

Genertor 函数是es6 新增的一种异步编程的解决方案,语法和传统的函数完全不同;Genertor 函数的最大的特点就是可以交出函数的执行权(即暂停执行)。

特征:

1、function关键字与函数名之间有一个星号

2、函数体内部使用yield表达式(暂停执行的标记),定义不同的内部状态

运行逻辑:

1、遇到 yield 表达式,就暂停执行后面的操作,并将紧跟在 yield 后面的那个表达式的值,作为返回的对象的 value 属性值。

2、下一次调用 next 方法时,再继续往下执行,直到遇到下一个 yield 表达式。

3、如果没有再遇到新的 yield 表达式,就一直运行到函数结束,直到 return 语句为止,并将 return 语句后面的表达式的值,作为返回的对象的 value 属性值。

4、如果该函数没有 return 语句,则返回的对象的 value 属性值为 undefined 。

注意:Generator并不是为异步而设计出来的,它还有其他功能(对象迭代、控制输出、部署Interator接口...)

4、async/await

Generator函数的语法糖。更为简洁,语义化更强。

async 作为一个关键字放到函数的前面,用于表示函数是一个异步函数,该函数的执行不会阻塞后面代码的执行。await是等待,只能放到async函数里面,在后面放一个返回promise对象的表达式

优点:

简洁、流程清晰,直观、语义明显。使用async和await明显节约了不少代码,不需要.then,不需要写匿名函数处理promise的resolve的值,不需要定义多余的data变量,还避免了嵌套代码。
内置执行器,Generator 函数的执行必须依靠执行器,而 Aysnc 函数自带执行器,调用方式跟普通函数的调用一样
async/await让try/catch 可以同时处理同步和异步错误。try/catch不能处理JSON.parse的错误,因为他在promise中。此时需要.catch,这样的错误处理代码非常冗余。并且,在我们的实际生产代码会更加复杂
返回值是 Promise,async 函数返回值是 Promise 对象,比 Generator 函数返回的 Iterator 对象方便,可以直接使用 then() 方法进行调用

 三、async/await与promise的区别

相同点:promise和 async/await都是解决异步编程的一种方式

区别:

1、promise编写代码相比Generator、async更为复杂化,且可读性也稍差

2、Generator、async需要与promise对象搭配处理异步情况

3、async实质是Generator的语法糖,相当于会自动执行Generator函数

4、async使用上更为简洁,将异步代码以同步的形式进行编写,是处理异步编程的最终方案

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃彩虹吐司的安琪拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值