关于Promise,你知道这些吗🐶

863 阅读4分钟

提到Node.js,就不可避免的聊到异步编程这个东西。早期的解决方案都是通过回调函数和事件来实现的,无可置疑,它们都很合理且强大,而且很早广泛被广大开发者和社区所认可;后来,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

回调函数处理异步

大家都知道,对于Node.js的很多操作都是异步的,目的主要是为了提高效率,充分利用硬件性能;但是异步操作也有它的弊端,那就是:异步操作是无序的。同一时间执行的异步操作,可能会在单位时间内以不同的先后次序完成。

使用回调函数相互嵌套就能解决这个问题。

但是这种写法太过复杂和冗余,而过多的回调也不利于代码维护和美观性;最要命的是,如果处理的数据太多,工作量就会及其庞大,所以也被称为地狱回调

各位码农苦不堪言,强烈要求ES6给大家伙搞一个NB点的对象来解决这件事

image.png

于是,“Promise”,应运而生。

所谓Promise,简单来说就是一个处理异步操作的容器,主要目的就是为了实现异步的有序化 image.png

promise对象有三个状态

1、pending(进行中)

2、fulfilled(已成功)

3、rejected(已失败)

只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected

Promise实例一旦创建,就会开始执行其内部代码,且一定是异步执行,即状态默认为pending(进行中) 不要在promise里去处理异步结果,而是执行promise的resolve与reject方法

Promise对象还有一些非常好用的对象方法

一、catch方法

用于捕获异步操作的错误信息

任何一个异步错误都会导致错误捕获,错误捕获后,将终止异步,停留在当前一级

createPromise('a').then(res => {
  console.log(res)
  //在前一个promise对象的then方法中返回下一个函数
  return createPromise('bbbb')//此行错误
}).then(res => {
  console.log(res)
  return createPromise('c')
}).catch(err => {
  console.log('Err has been caught')
  console.log(err)
})

二、all方法

将多个Promise合并成一个Promise,所有异步全部执行完毕才会执行then方法

封装创建promise函数,函数名为createPromise

let p1 = createPromise('a')
let p2 = createPromise('b')
let p3 = createPromise('c')
//使用all方法
let pAll = Promise.all([p1, p2, p3])

//直接在all方法基础上调用then方法
pAll.then(data => {
  console.log(data)
}).catch(err => {
  console.log(err)
})

三、race方法

将多个Promise合并成一个Promise

任何一个异步执行完毕就会执行then方法

封装创建promise函数,函数名为createPromise

let p1 = createPromise('a')
let p2 = createPromise('b')
let p3 = createPromise('c')
//使用all方法
let pRace = Promise.race([p1, p2, p3])

//直接在all方法基础上调用then方法
pRace.then(data => {
  console.log(data)
}).catch(err => {
  console.log(err)
})

三个promise任何一个成功,就去执行pRace.then的第一个方法;一旦成功一个,其他不再执行

(其实就是比谁快,谁第一个成功,其他的就不执行)

ES6异步函数async与await

这样一来写法就要合理不少,重复代码大大减少了

但是!!!在then方法中依旧能看到回调的影子,于是在Promise的基础上,ES6再接再厉,给了我们更加实用的函数套件 => 异步函数asyncawait

异步函数async相当于是promise语法的高级写法,ES2017中引入的更为高级的异步处理机制,可以让异步的处理变的更加便捷

promise虽然解决了异步回调地狱(回调函数层次嵌套)的问题,但是写起来的时候仍然需要嵌套(链式语法嵌套,需要在上一个promise对象的then方法中返回下一个promise)

直接使用async对已有函数进行修饰,

async function fn() {}

或者直接使用async声明箭头函数

const readFile = async () => {}

async关键字: 修饰函数,表示这个函数内部有异步操作

await关键字: 等待异步执行完毕

(1)await只能用于被async修饰的函数中 只有当await后面的异步操作执行完毕后,才会继续执行后面代码

(2)await 后面只能是promise对象

这两个关键字只能用于函数, 所以用的时候一定要放在函数里面用!!!

封装创建promise函数,函数名为getPromise

const readFile = async () => {
  //async异步函数的错误信息要用try-catch来捕捉
  try {
    let res1 = await getPromise('a')
    console.log(res1)
    let res2 = await getPromise('b')
    console.log(res2)
    let res3 = await getPromise('c')
    console.log(res3)
  } catch (err) {
    console.log(err)
  }
}
//调用函数
readFile()

async异步函数的错误信息要用try-catch来捕捉

参考文献: Promise 对象 - ECMAScript 6入门