ES6——promise对象

226 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Promise的含义

Promise 是针对于异步编程的一种解决方案,在Pormise没有被提出之前,我们处理异步代码都是用回调函数的方法,但大量的回调函数会引起内存泄露,导致代码的执行速度下降。Promise相比于传统的解决方案——回调函数和事件——更加合理和强大。所以在中ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

Promise的基本用法

Promise函数接收一个函数作为参数,这个函数可以有两个参数,一个是成功函数(resolve),一个是失败函数(reject)。Promise的.then接收两个回调函数,一个是成功函数的回调,一个是失败函数的回调。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。

   const myPromise = new Promise(function (resolve, reject) {
       resolve()
       reject()
   });
   myPromise.then(function (value) { //成功
       console.log('success');
   }, function (error) { //失败
       console.log('file');
   })

resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。Promise对象中的状态不会被外界干扰。状态的改变取决于异步的操作结果。成功即执行reslove函数,失败即执行reject。且Promise对象的状态一旦被改变,就不会进行再次改变。

Promise的方法

1.Promise.prototype.then()

then方法的返回结果是新的Promise实例,对象状态由回调函数的执行结果决定。then方法后面还可以再调用另一个then方法,形成链条。采用链式的then,可以指定一组按照次序调用的回调函数。

function xq() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('相亲了!');
        resolve('ok')
      }, 2000)
    })
  }
function marry() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('结婚了');
        resolve('好开心')
      }, 1000)
    })  
  }
function baby() {
   setTimeout(() => {
      console.log('出生了!');
    }, 500)
  }
  xq()
    .then(marry)
    .then(baby)

微信图片_20220720185056.png

在上面这段异步代码中,当我想让他们按照相亲、结婚、出生的顺序执行的话,我们就要给他们加上promise对象,当我们在调用xq函数时我们在后面加入.then方法返回一个新的promise对象执行marry函数,再在marry函数中加入.then方法再返回一个新的promise对象执行baby函数。让它的执行顺序为相亲、结婚、出生。

2.Promise.prototype.catch()

catch()用于指定发生错误时的回调函数,在下面这段代码中,我们用a.catch(funtion(error))将上面promise中的失败函数的结果打印出来了。

function a() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('aaa');
      reject('fail');
    }, 1000)
  });
}
a().catch(function (error) {
  console.log(error);
})

微信图片_20220720192052.png

3.Promise.prototype.finally()

finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。而且finally方法总是会返回原来的值。在下面这段代码中,a函数虽然回调失败,返回了reject,但是c函数还是执行了。

function a() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('aaa');
      reject('fail');
    }, 1000)
  });
}
function c() {
  setTimeout(() => {
    console.log('ccc');
  }, 500)
}
a().finally(c)

微信图片_20220720193451.png 4.Promise.all()

all()是将多个 Promise 实例,包装成一个新的 Promise 实例。接收一个数组作为参数,数组的每一项都是Promise对象的实例。如果不是,会通过Promise.resolve()将参数转为Promise实例,再进行处理。all()用于将多个 Promise 实例,包装成一个新的 Promise 实例。在下面这段代码中,只有all()所有的promise实例执行完,C函数就会执行。

function a() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('aaa');
      resolve('ok');
    }, 1000)
  });
}
function b() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('bbb');
      resolve('ok');
    }, 2000)
  });
}
function c() {
  setTimeout(() => {
    console.log('ccc');
  }, 500)
}
 Promise.all([a(), b()]).then(c)

微信图片_20220720200602.png 5.Promise.race()

race()是将多个 Promise 实例,包装成一个新的 Promise 实例。接收一个数组作为参数,数组的每一项都是Promise对象的实例。如果不是,会通过promise.resolve()将参数转为Promise实例,再进行处理。只要参数的Promise实例有一个率先改变状态,则状态改变。在下面这段代码中,只要race()有一个promise实例执行完,C函数就会执行。

function a() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('aaa');
      resolve('ok');
    }, 1000)
  });
}
function b() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('bbb');
      resolve('ok');
    }, 2000)
  });
}
function c() {
  setTimeout(() => {
    console.log('ccc');
  }, 500)
}
 Promise.race([a(), b()]).then(c)

微信图片_20220720200703.png

Promise的应用场景和不足之处

Promise的应用场景具体有:

  1. Ajax请求
  2. 文件读取
  3. 图片加载
  4. 函数封装

上述这几个场景中,基本都涉及成功和失败。我们可以用Promise同时对其成功或失败进行不同的处理。使我们的代码可以处理更多不同的情况。

Promise的不足之处具体有:

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

Promise虽然解决了回调函数的问题,但是它也存在一些未解决的问题,也许在未来我们可以找到更好的方法去解决它。