基本介绍
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
基本用法
1.创建一个Promise实例
const promise = new Promise((resolve, reject) => {
// ... some asynchronous working
if (/* fulfilled */){
return resolve(value)
} else { // rejected
return reject(error)
}
})
Promise
构造函数接受一个函数作为参数,该函数的两个参数分别是resolve
和reject
。它们是两个函数,由JavaScript
引擎提供,不用自己部署。
-
resolve:
pending ——> fulfilled;
在异步操作成功时调用,并将异步操作的结果作为参数传递出去。
-
reject:
pending ——> rejected;
在异步操作失败时调用,并将异步操作的错误,作为参数传递出去。
一般来说,调用
resolve
或reject
以后,Promise
的使命就完成了,后继操作应该放到then
方法里面,而不应该直接写在resolve
或reject
的后面。所以,最好在它们前面加上return
语句,这样就不会有意外。
2.Promise.prototype.then()
promise.then((value) => {
// resolved
}, (error) => {
// rejected
})
then
方法可以接受两个回调函数作为参数。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。
-
回调函数1:
Promise对象的状态变为resolved时调用。
-
回调函数2(可选):
Promise对象的状态变为rejected时调用。
3.Promise.prototype.catch()
promise.then((value) => {
// resolved
}).catch((error) => {
// 1.rejected
// 2.then内部发生错误
})
Promise.prototype.catch
方法是.then(null, rejection)
或.then(undefined, rejection)
的别名,用于指定发生错误时的回调函数。
Promise
对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch
语句捕获。
一般来说,不要在
then
方法里面定义Reject
状态的回调函数(即then
的第二个参数),总是使用catch
方法。
4.Promise.prototype.finally()
该方法是 ES2018 引入标准的。
promise.then(result => {
// resolved
}).catch(error => {
// 1.rejected
// 2.then内部发生错误
}).finally(() => {
// 与状态无关
})
finally
方法的回调函数不接受任何参数,这意味着没有办法知道,前面的Promise
状态到底是fulfilled
还是rejected
。这表明,finally
方法里面的操作,应该是与状态无关的,不依赖于Promise
的执行结果。
finally
方法总是会返回原来的值。
finally
本质上是then
方法的特例。
实现:
Promise.prototype.finally = function (callback) {
let P = this.constructor
return this.then(
// 不管前面的 Promise 是fulfilled还是rejected,都会执行回调函数callback
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
)
}
5.Promise.all([p1, p2])
const p = Promise.all([p1, p2])
参数:
- p1、p2都是
Promise
实例; - 如果不是
Promise
实例,则会先调用Promise.resolve()
将其转为Promise
实例; - 可以不是数组,但必须具备
Interator
接口。
返回值:
- 只有p1、p2的状态都变成
fulfilled
,p的状态才会变成fulfilled
,此时p1、p2的返回值组成一个数组,传递给p的回调函数。
const p1 = new Promise((resolve) => {
setTimeout(() => {
console.log('p1')
return resolve('p1 resolved')
}, 3000)
})
const p2 = new Promise((resolve) => {
setTimeout(() => {
console.log('p2')
return resolve('p2 resolved')
}, 1000)
})
Promise.all([p1, p2]).then((result) => {
console.log(result)
})
2.只要p1、p2之中有一个被rejected
,p的状态就变成rejected
,此时第一个被reject
的实例的返回值,会传递给p的回调函数。
const p1 = new Promise((resolve) => {
setTimeout(() => {
console.log('p1')
return resolve('p1 resolved')
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('p2')
return reject('p2 rejected')
}, 1000)
})
Promise.all([p1, p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error)
})
- 如果作为参数的
Promise
实例,自己定义了catch
方法,那么它一旦被rejected
,并不会触发Promise.all()
的catch
方法。
const p1 = new Promise((resolve) => {
setTimeout(() => {
console.log('p1')
return resolve('p1 resolved')
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('p2')
return reject('p2 rejected')
}, 1000)
}).catch((error) => {
console.log(error)
})
Promise.all([p1, p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error)
})
6.Promise.race([p1, p2])
const p = Promise.race([p1, p2])
参数:
- 同
Promise.all(p1, p2)
。
返回值:
- 只要p1、p2之中有一个实例率先改变状态,p的状态就跟着改变。
// p2提前被rejected
const p1 = new Promise((resolve) => {
setTimeout(() => {
console.log('p1')
return resolve('p1 resolved')
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('p2')
return reject('p2 rejected')
}, 1000)
})
Promise.race([p1, p2]).then((result) => {
console.log(result)
})
.catch((error) => {
console.log(error)
})
// p1提前被resolved
const p1 = new Promise((resolve) => {
setTimeout(() => {
console.log('p1')
return resolve('p1 resolved')
}, 1000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('p2')
return reject('p2 rejected')
}, 3000)
})
Promise.race([p1, p2]).then((result) => {
console.log(result)
})
.catch((error) => {
console.log(error)
})
7.Promise.resolve()
有时需要将现有对象转为 Promise
对象。
Promise.resolve('result')
// 等价于
new Promise(resolve => resolve('result'))
8.Promise.reject()
Promise.reject('erroe')
// 等价于
new Promise((resolve, reject) => reject('error'))
小结
Promise
使得异步编程更为简介与强大,本文主要通过几个简单demo介绍了Promise
的基本使用,后续章节将会继续讲解其它异步编程方式。