加入收藏 | 设为首页 | 会员中心 | 我要投稿 91站长网 (https://www.91zhanzhang.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 编程要点 > 语言 > 正文

Promise使用方法是什么?一文带你深入了解Promise

发布时间:2022-01-11 16:47:23 所属栏目:语言 来源:互联网
导读:这篇文章主要给大家分享Promise使用方法,下文有详细的介绍Promise是什么、Promise的基本用法等等,对大家学习和理解Promise都有一定的帮助,感兴趣的朋友可以了解看看,接下来我们一起来学习一下吧。 1、什么是Promise 我的理解是:实现让我们用同步的方式
   这篇文章主要给大家分享Promise使用方法,下文有详细的介绍Promise是什么、Promise的基本用法等等,对大家学习和理解Promise都有一定的帮助,感兴趣的朋友可以了解看看,接下来我们一起来学习一下吧。
 
  1、什么是Promise
  我的理解是:实现让我们用同步的方式去写异步代码的一种技术。是异步解决方案的一种。
 
  他可以将多个异步操作进行队列化,让它们可以按照我们的想法去顺序执行。
 
  那么,Promise之前有没有其他的异步解决方案。肯定是有的,常见的有callback回调函数以及事件。
 
  那Promise有啥优势,我认为Promise功能更为强大,且能让我们代码写的更为清晰
 
  Promise提供了统一的API, 让我们控制异步操作更加容易
  Promise可以避免callback回调函数的层层嵌套,使代码更为清晰。可读性性与维护性更高
  2、Promise基本用法
  首先,我们先来了解一些Promise的基本概念
 
  2.1、Promise状态
  Promise一共有3中状态,分别是Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)
  状态的改变只可能从Pending转------>Resolved,或者从Pending------->Rejected。并且状态一旦发生改变,就不会再更改了。而触发状态发生改变的,只有异步操作的结果。结果为成功 触发状态变更为 Resolved, 结果失败或者中途发生错误,则会触发状态变更为 Rejected
 
  2.2 Promise结构
  Promise是一个构造函数,故通过new Promise()可以实例化出来一个Promise对象
 
  new Promise()时,接受一个函数作为参数,且这个函数,有两个参数,分别是resolve,reject。 而resolve和 reject也是两个函数。他们由JavaScript引擎提供,不用自己部署。
 
  每一个被实例化出来的promise实例,都有.then() 和 .catch() 两个方法。且这两个方法的调用支持链式操作
 
  好,了解完概念,我们看看Promise的基本用法
 
  首先,如何实例化一个promise对象
 
  const promise = new Promise((resolve, reject) => {
   setTimeout(() => {
   if (/* 成功 */) {
   resolve(res)
   } else {
   reject(err)
   }
   }, 100)
  })
  上图中,通过new Promise() 实例化了一个promise实例,注意:new Promise()方法中的函数是一个立即执行函数,即,在new Promise()的一瞬间就会被执行。函数内代码是同步代码。
 
  resolve和reject用于返回异步操作的结果,当使用resolve()时,promise状态会由Pending―>Resolved, 并将异步的正确结果返回。当使用reject()时,promise状态由Pending---->Rejected,并将错误信息返回
 
  再看这个对象如何接收返回的结果
 
  promise.then((res) => {
   console.log(res)
  }).catch((err) => {
   console.log(err)
  })
  上图中,.then的回调函数 和 .catch的回调函数分别用来接收resolve()返回的正确信息和reject返回的错误信息。
 
  下面我们来详细看下.then() 和 .catch()
 
  .then() 函数
 
  then()函数是Promise实例的一个方法,他的作用是为Promise实例添加状态改变时的回调函数
  它存在以下特点
 
  then()是添加在Promise的原型上的。即Promise.prototype.then(), 故所有Promise实例都存在.then()方法
  .then()可以进行链式操作 即promise.then().then().then(),then的回调函数将会按照次序调用
  .then()函数存在两个参数,这两个参数一般情况下是函数。其中,第一个函数是在状态变为Resolved的时候才会执行(我们下文中统称为.then的resolve回调),并且参数是Promise对象resolve(res)时的值。第二个函数是在状态变为Rejected的时候才会执行(我们下文统称为.then的reject回调),后面我们会说哪几种情况下,状态会变成Rejected
  Promise会存在值穿透的情况,当我们then()的两个参数不为函数时,会穿透到下一个then()里面,如果下一个then()参数也不是函数,则会继续向下穿透
  我们上面说过了,Promise实例resolve()方法执行时,会将实例的状态变更为Resolved,故.then的resolve回调会在当前Promise实例resolve()时被触发
  下面,我们重点来分析下第2,3,4,5
 
  function getData(url) {
   return new Promise((resolve, reject) => {
   setTimeout(() => {
    if (url) {
    resolve({
     code: 200,
     message: 'ok',
     data: 123
    })
    } else {
    reject(new Error('缺少url'))
    }
   }, 100)
   })
  }
  getData('http://www.baidu.com').then((res) => {
   console.log('第一个回调')
   console.log(res)
  }).then((res) => {
   console.log('第二个回调')
   console.log(res)
  }).then((res) => {
   console.log('第三个回调')
   console.log(res)
  })
  // 第一个回调
  // { code: 200, message: 'ok', data: 123 }
  // 第二个回调
  // undefined
  // 第三个回调
  // undefined
  可以看出,首先,当getData() resolve() 执行时 .then的resolve回调函数被依次调用,但是只有第一个then()的resolve回调函数的参数有值,而其他两个是undefind,这是为什么呢?我们再来看一个代码
 
  getData('http://www.baidu.com').then((res) => {
   console.log('第一个回调')
   console.log(res)
   return Promise.resolve()
  }).then((res) => {
   console.log(res)
  })
  // 第一个回调
  // { code: 200, message: 'ok', data: 123 }
  // undefined
  看这个代码我们可以发现,上一个then的resolve回调当return一个Promise.resolve()时,和我们不return 任何东西时得到的结果是一样的。那我们是不是可以理解为,每个.then()方法的resolve回调函数,执行完后默认都会返回一个Promise.resolve()。没错,我告诉你,是的。
 
  至于Promise.resolve()得到的是一个什么,我先告诉你,他得到的是一个resolve状态的Promise实例。这个后面我们会再讲。
 
  此时,我们可以总结出:从第二个.then()开始,调用这个.then的resolve回调函数的-----是上一个.then的resolve回调所返回的Promise实例。而.then回调函数的参数,便是上一个.then的回调函数所返回的Promise实例resolve的值。下面我们看一段代码验证一下
 
  getData('http://www.baidu.com').then((res) => {
   console.log('第一个回调')
   console.log(res)
   return new Promise((resolve, reject) => {
   resolve('123')
   })
  }).then((res) => {
   console.log(res)
  })
 
  // 第一个回调
  // { code: 200, message: 'ok', data: 123 }
  // 123
  总结:
 
  每一个.then的resolve回调都会返回默认返回一个Resolved状态的Promise对象
  当你收到return了一个新的Promise实例时,会覆盖默认返回的Promise实例
  返回的Promise实例resolve()的值,会作为下一个.then的resolve回调的参数返回
  下面我们再来看下,如果then()的参数不是函数,那会怎么样,下面,我们看一段代码
 
  var getData = function() {
   return new Promise(function(resolve, reject) {
    resolve(123)
   });
  };
  getData().
  then(345)
  .catch(err => {
   console.log('捕捉到一个错误')
   console.log(err)
  }).then((res) => {
   console.log('我是第二个then')
   console.log(res)
  })
  // 输出
  我是第二个then
  123
  如上图,可以看到,当我们第一个then的resolve回调不是函数,而是一个数字345时,resolve(123)穿透到第二个then中了,触发了第二个then的resolve回调执行,并将resolve的返回值给了第二个then的resolve回调。这种现象,叫做值穿透。
 
  var getData = function() {
   return new Promise(function(resolve, reject) {
    reject(new Error(123))
   });
  };
  getData().
  then(345)
  .catch(678)
  .then((res) => {
   console.log('我是第二个then')
   console.log(res)
  }).catch(err => {
   console.log('我是第二个catch')
   console.log(err)
  })
  // 输出
  我是第二个catch
  Error: 123
  可以看到,报错时,同样发生了值穿透
 
  到此,.then()相关以及 then()的第一个参数就讲完了,而第二个参数,我们放到.catch()方法中一起将
 
  .catch() 函数
 
  catch()也是挂载在Promise对象原型下的方法(Promise.prototype),和then()一样, 故所有Promise对象也都有catch方法。它的作用是用来指定发生错误时的回调函数,也就是捕获异步操作所发生的错误
  它有什么特点呢。我们先总结一下,后来再一一来验证
 
  .catch()会指定一个参数作为错误发生时的回调,故catch((err) => {})的参数会在Promise状态变更为Rejected时被触发。
  .then(null, (err) => {})的第二个参数,也是在Promise状态变更为Rejected时被触发。故其实.catch()和 .then()的reject回调函数本质上是一样的,只是写法不一样。但我们一般更倾向于使用.catch()而不使用.then的reject回调。原因后面会讲
  代码抛出错误和reject()函数执行都会让Promise对象的状态转变为Rejected,故两种情况都会触发catch()的回调执行或者then()的reject回调执行。 所以,reject()的本质,其实就是抛出一个错误
  .catch()的回调函数以及.then的reject回调一样,执行时默认都会返回一个状态为Resolved的Promise对象(也就是 return Promise.resolve())
  .catch()和.then()一样,也可以写多个,也支持链式操作,原因就是上面的第三点
  抛出的错误一旦被catch捕获,便不会再向外传播,只有再次向外抛出错误,才会继续被后面的catch所捕获。故错误具有冒泡性质,会一步一步向外传播,直到被catch捕获
  1、我们先看第一点:
 
  var getData = function() {
   return new Promise(function(resolve, reject) {
    reject(123)
   });
  };
  getData().then((res) => {
   console.log('成功')
  }).catch((err) => {
   console.log('捕捉到错误')
   console.log(err)
  })

(编辑:91站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读