Promise对象

Promise对象

定义

promise是一个对象,用来保存异步操作之后的结果。

promise的状态只由异步操作的结果决定,分别有pending(进行中)、fulfilled(成功)、rejected(失败)。

promise一创建就会执行,无法取消,无法终止。

promise提供统一的API,各种异步操作都可以用同样的方法处理

解决了什么问题

promise的链式调用解决了回调地狱、callback层层嵌套的问题

promise让代码简洁易懂,易于维护

基本用法

使用Promise()构造函数接收一个函数作为参数,该函数的两个参数分别是resolvereject。这两个参数是函数,由JavaScript引擎提供。

const promise = new Promise((resolve,reject) => {
    //write some code
    if(/*异步操作成功*/){
       resolve(value)
    } else{
        reject(error)
    }
})

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

promise.then(function(success){
	console.log(success)
},function(error){
	console.log(error)
})

之后学了catch方法可以改写成下面这个样子

promise.then(success => {
	console.log(success)
}).catch(error => {
    console.log(error)
})

API

Promise.prototype.then()

promise实例有then方法,它接收两个函数作为参数,第一个是resolved状态的回调函数,第二个是rejected状态的回调函数(可选)

采用链式的then,可以按照指定的次序调用回调函数,then接收上一个回调函数传过来的promise对象或者结果。

getJSON("/post/1.json").then(
  post => getJSON(post.commentURL)
).then(
  comments => console.log("resolved: ", comments),
  err => console.log("rejected: ", err)
);
Promise.prototype.catch()

catch方法是接收错误的回调函数,用于捕获抛出错误。

getJSON('/posts.json').then(function(posts) {
  // ...
}).catch(function(error) {
  // 处理 getJSON 和 前一个回调函数运行时发生的错误
  console.log('发生错误!', error);
});

注意,如果在catch前面的回调函数抛出错误,都会被catch捕获,Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。

所以,一般来说,不要在then方法中定义reject的回调函数,而是使用catch方法

Promise.prototype.finally()

不管promise最后的状态是什么,finally都会执行操作

promise.then(success => {...})
.catch(error => {...})
.finally(() => {/*都会执行的操作*/})

finally不接收任何参数,无法判断promise返回的状态是fulfilled还是rejected,就是说,finally进行的操作,应与promise的状态无关,不依赖与promise返回的结果, 本质上是then方法的特例。

Promise.all()

用于将多个 Promise 实例,包装成一个新的 Promise 实例

const p = Promise.all([p1,p2,p3])

Promise.all()接收一个由Promise实例组成的数组(或者是具有Iterator接口可以遍历且返回的成员都是Promise实例的对象?)

上述代码中,p的状态由Promise实例决定,有两种情况

1、所有的promise实例状态变成fulfilled,p的状态才变成fulfilled,接收是一个包含各个实例结果的数组

2、其中一个promise实例的状态变成rejected,则p的状态变成rejected,且第一个被reject的实例返回值,会传给p的回调函数

const p1 = new Promise((resolve, reject) => {
  resolve('hello');
})
.then(result => result)
.catch(e => e);

const p2 = new Promise((resolve, reject) => {
  throw new Error('报错了');
})
.then(result => result)
.catch(e => e);

Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 报错了]

上面代码中,p1resolvedp2首先会rejected,但是p2有自己的catch方法,该方法返回的是一个新的 Promise 实例,p2指向的实际上是这个实例。该实例执行完catch方法后,也会变成resolved,导致Promise.all()方法参数里面的两个实例都会resolved,因此会调用then方法指定的回调函数,而不会调用catch方法指定的回调函数。

const p1 = new Promise((resolve, reject) => {
  resolve('hello');
})
.then(result => result);

const p2 = new Promise((resolve, reject) => {
  throw new Error('报错了');
})
.then(result => result);

Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// Error: 报错了

如果p2没有自己的catch方法,就会调用Promise.all()catch方法。

Promise.race()

raceall一样,同样是将多个promise实例包装成一个新的promise实例,不同的是,哪一个promise实例最率先改变状态,那么race将接收这个实例返回的结果传递给回调函数。

Promise.allSettled()

Promise.allSettled()方法接受一组Promise实例作为参数,包装成一个新的Promise实例,只有等这一组实例都返回结果,即不管是fulfilled还是rejected,包装实例才会结束。

该包装实例的状态总是fulfilled,接收的参数是一个包含promise实例组的解决状态和返回结果的对象数组

Promise.any()

Promise.any()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。

var resolved = Promise.resolve(42)
var rejected = Promise.reject(-1)
var alsoRejected = Promise.reject(Infinity)
Promise.any([resolved,rejected,alsoRejected]).then((result) => {
    console.log(result) // 42
}).catch((error) => {
    console.log(error) // [-1,Infinity]
})
Promise.resolve()

Promise.resolve()将一个现有对象转为Promise对象。

1、参数是一个Promise实例

Promise.resolve()将原封不动返回这个实例

2、参数是一个thenable对象

thenable对象是指这个对象具有then方法,如下代码所示

let thenable = {
	then:function(resolved,reject){
		resolved('haha')
	}
}

使用Promise.resolve()会将这个对象转为Promise对象,然后立即执行这个thenable对象中的then方法。而转化后的promise对象的回调函数会接收thenable对象中的then方法执行后的状态和返回的结果。

3、参数不具有then方法和对象,或根本不是对象

如果传入的参数是这种情况,那么Promise.resolve会直接将这个传入参数转化为promise对象,并且状态为resolved,因为不存在异步操作。

4、无参数

直接返回一个resolved状态的 Promise 对象。

需要注意的是,立即resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时。 当同时有setTimeoutPromise.resolve时,resolve会先执行,因为setTimeout是在下一轮"事件循环"开始执行的。

Promise.reject()

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected

注意,Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。这一点与Promise.resolve方法不一致。

const thenable = {
  then(resolve, reject) {
    reject('出错了');
  }
};

Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable) // true 这个e不是“出错了”字符串,而是thenable这个对象
})
Promise.try()

应用

1、promiseajax结合

2、promise处理异步队列

3、promise超时请求处理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值