JavaScript Promise详解 resolve()、reject()、then()、catch()、finally()(包含习题)

Promise

Promise是个十分优雅的词,他的中文含义是承诺、约定的意思,在古今中外都有非常多的和“承诺”相关的历史故事、寓言故事和名言名句,那么今天我们就来一起了解下JavaScript中的Promise吧!
在这里插入图片描述


一、Promise基础

在这里插入图片描述

promise是ES6新增的引用类型,可以通过 new 操作符来实例化。创建新的promise需要传入执行器(executor)函数作为参数。

我们new一个Promise实例:

const promise = new Promise(function(resolve, reject) {
    resolve(value);
});

Promise对象有以下两个特点。

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

特点一: promise的状态一旦改变就无法更改

我们看一个例子就可以清晰了解到promise的状态特点:

const p = new Promise((resolve,reject) => {
    resolve()
    reject()
})
const p2 = new Promise((resolve,reject) => {
    reject()
    resolve()
})
console.log(p)//Promise {<fulfilled>: undefined}
console.log(p2)//Promise {<rejected>: undefined}


所以我们总结promise的第一个特点: promise的状态一旦改变就无法更改

特点二:promise实例内部本身是同步执行的

在初始化promise时,执行器已经改变了每个promise的状态。我们知道执行器函数是同步执行的。我看看一个例子:

console.log('a')

setTimeout(function(){
    console.log('f')
}, 200)
const p = new Promise(resolve => {
    console.log('b')
    resolve('g')
    console.log('c')
})
setTimeout(function(){
    console.log('e')
}, 0)

console.log('d')

//答案:
/*
	 a
	 b
	 c
	 d
	 e
	 f
*/

如果看不懂执行js执行机制可以先阅读我上一篇文章【JavaScript】JS执行机制微任务和宏任务
所以我们总结promise的第二个特点:promise本身是同步执行的

二、promise的静态方法

这里先介绍两个最基本的静态方法,下一篇文章会带来:raceallSettledAllany的拓展静态方法

Promise.resolve()

通过调用Promise.resolve()方法我们可以实例化一个解决的Promise
下面两个实例的结果实际上是一样的:

const p1 = new Promise(resolve => {
    resolve()
})
const p2 = Promise.resolve()
console.log(p1)//Promise {<fulfilled>: undefined}
console.log(p2)//Promise {<fulfilled>: undefined}
console.log(p1==p2)

Promise.reject()

Promise.resolve()一样,Promise.reject()实例化一个拒绝状态的Promise并抛出错误。
下面两个实例的结果实际上是一样的:

const p1 = new Promise(reject => {
    reject()
})
const p2 = Promise.reject()
console.log(p1)//Promise {<rejected>: undefined}
console.log(p2)//Promise {<rejected>: undefined}

三、Promise的实例方法

1、Promise.then()

Promise.then()接收最多两个参数:onResolvedonRejected。两个参数都是可选的,如果提供的话promise会进入“fulfilled”和“rejected”状态时执行。
我看来看一下例子:

const p1 = new Promise((resolve,reject )=> {
  setTimeout(function(){
      resolve('我是resolve,成功状态');
    }, 2000);
  });


const p2 = new Promise((resolve,reject )=> {
  setTimeout(function(){
      reject ('我是reject,失败状态');
    }, 2000);
  });

p1.then((res)=>{ console.log(res)},(err)=>{ console.log(err)}) //我是resolve,成功状态

p2.then(null,(err)=>{ console.log(err)})// 我是reject,失败状态

因为期约状态只有一次所以onResolvedonRejected这两个操作一定是互斥的。
传给.then()的任何非函数类型的参数都会被静默忽略。所以我们一般只提供一个参数,那么在另一个状态的参数上我们传入null。可以有助于避免在内存中创建多余的对象
我们根据特性:传给.then()的任何非函数类型的参数都会被静默忽略做一道习题:

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)
  
  //第一个then和第二个then中传入的都不是函数,一个是数字,一个是对象,因此发生了透传,将resolve(1) 的值直接传到最后一个then里。

所以输出结果为:1

2、Promise.catch()

catch方法用于给Promise添加拒绝处理程序。这个方法只接收一个参数,事实上他就是.then的一个语法糖,调用它就相当于上文中的:

Promise.then(null,(err)=>{ console.log(err)})

根据(事实上他就是.then的一个语法糖)这一个特点,我们再来结合Promise特点一(promise的状态一旦改变就无法更改) 和 .then的特点(Promise.then()接收最多两个参数:onResolved和onRejected)做一道综合练习题:

Promise.reject('err!!!')
  .then((res) => {
    console.log('success', res)
  }, (err) => {
    console.log('error', err)
  }).catch(err => {
    console.log('catch', err)
  })
// 在这道题中,错误直接被then的第二个参数捕获了,所以就不会被catch捕获了,输出结果为:'error' 'error!!!'

3、Promise.finally()

finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。

promise.then((result) => {/* ···*/})    .catch((error) => {/* ···*/})    .finally(() => {/* ···*/});

下面是一个例子,服务器使用 Promise 处理请求,然后使用finally方法关掉服务器。

server.listen(port)    .then(function() {    /* ... */   })    .finally(server.stop);

finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。
我们来看一道习题了解finally的特性:

Promise.resolve('1')
  .then(res => {
    console.log(res)
  })
  .finally(() => {
    console.log('finally')
  })
Promise.resolve('2')
  .finally(() => {
    console.log('finally2')
  	return '我是finally2返回的值'
  })
  .then(res => {
    console.log('finally2后面的then函数', res)
  })
/*
	结果: 
	1
	finally2
	finally
	finally2后面的then函数 2
*/

finally本质上是then方法的特例。

总结

那么最后总结一下 promise的几个小特点:

  1. 特点一: promise的状态一旦改变就无法更改
  2. 特点二:promise实例内部本身是同步执行的
  3. 特点三:Promise.then()接收最多两个参数:onResolvedonRejected。两个参数都是可选的,如果提供参数的话promise会进入“fulfilled”和“rejected”状态时执行。
  4. 特点四:传给.then()的任何非函数类型的参数都会被静默忽略
  5. 特点五:Promise.catch()只接收一个参数。事实上他就是.then的一个语法糖 相当于:Promise.then(null,(err)=>{ console.log(err)})只是我们不用传递第一个null参数了
  6. 特点六:Promise.finally() 方法不管Promise对象最后的状态如何都会执行
  7. 特点七:finally()方法的回调函数不接受任何的参数,也就是说你在.finally()函数中是无法知道Promise最终的状态是resolved还是rejected的
  8. 特点八:finally()它最终返回的默认会是一个上一次的Promise对象值,不过如果抛出的是一个异常则返回异常的Promise对象。
  • 10
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值