ES6-Promise
基本概念
做异步请求时,我们往往会在请求成功的回调函数里继续写函数,或者继续发送异步,继续回调,回调函数里又回调,一层一层嵌套,就会形成回调地狱。这会使我们的代码可读性变差,不好维护,性能也下降,promise
可以解决回调地狱的问题
Promise
起到代理的作用,被代理的值在Promise
对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法,这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象
Promise
对象用于表示一个异步操作的最终状态(完成或失败),以及该异步操作的结果值
一个Promise
有以下几种状态:
pending
: 初始状态,既不是成功,也不是失败状态fulfilled
: 意味着操作成功完成rejected
: 意味着操作失败
只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
Promise
对象只可能会发生两种改变:
pending
状态变为fulfilled
状态并传递一个值给相应的状态处理方法pending
状态变为rejected
并传递失败信息
当其中任一种情况出现时,Promise
对象的then
方法绑定的处理方法就会被调用,then
方法包含两个函数作为参数:onfulfilled
和onrejected
当Promise
状态为fulfilled
时,调用onfulfilled
方法,反之调用onrejected
方法
基本用法
Promise
对象是一个构造函数,用来生成Promise
实例
1 | let promise = new Promise((resolve, reject) => { |
可以看到,Promise
构造函数接受一个函数作为参数,而该函数的两个参数分别为resolve
函数和reject
函数
当异步操作成功,也即是从
pending
状态变为fulfilled
状态时,调用resolve
,并将异步操作的结果作为参数传递出去当异步操作失败,也即是从
pending
状态变为rejected
状态时,调用reject
,并将异步操作的结果作为参数传递出去
在Promise
实例生成以后,可使用then
方法分别指定fulfilled
和rejected
状态的回调函数
1 | promise.then(value => { |
来看一个例子
1 | function timeout(ms) { |
timeout
方法返回一个Promise
实例,表示过一段时间后执行,当Promise
状态变为fulfilled
时就会触发then
绑定的回调函数
Promise
在新建后会立刻执行,then
方法指定的回调函数会在当前脚本所有同步任务执行完之后才会执行
1 | let promise = new Promise((resolve, reject) => { |
当异步操作失败,调用reject
,其参数通常是Error
对象的实例
1 | function loadImageAsync(url) { |
Promise
对象也可以作为参数被传入resolve
中
1 | let promise1 = new Promise((resolve, reject) => { |
promise1
的状态在3秒后改变,promise2
的状态在1秒后改变,由于promise2
返回的是promise1
,因此1秒后promise2
的状态由promise1
决定,故在两秒后触发catch
调用resolve
或者reject
并不会终止Promise
的执行
1 | new Promise((resolve, reject) => { |
一般在resolve
或者reject
前加return
1 | new Promise((resolve, reject) => { |
实例方法
Promise.prototype.then()
该方法可以为Promise
实例添加状态改变时的回调函数
1 | Promise.prototype.then(onFulfilled[, onRejected]) |
onFulfilled
: 第一个参数是fulfilled
状态的回调函数onRejected
: 第二个参数是rejected
状态的回调函数,可选
1 | function f(flag) { |
当一个Promise
成功或者失败,具体的返回值依据以下规则返回:
如果
then
中的回调函数返回一个值,那么then
返回的Promise
将会成为fulfilled
状态,并且将返回的值作为fulfilled
状态的回调函数的参数值如果
then
中的回调函数没有返回值,那么then
返回的Promise
将会成为fulfilled
状态,并且该fulfilled
状态的回调函数的参数值为undefined
如果
then
中的回调函数抛出一个错误,那么then
返回的Promise
将会成为rejected
状态,并且将抛出的错误作为rejected
状态的回调函数的参数值如果
then
中的回调函数返回一个已经是fulfilled
状态的Promise
,那么then
返回的Promise
也会成为fulfilled
状态,并且将那个Promise
的fulfilled
状态的回调函数的参数值作为该被返回的Promise
的fulfilled
状态回调函数的参数值如果
then
中的回调函数返回一个已经是rejected
状态的Promise
,那么then
返回的Promise
也会成为rejected
状态,并且将那个Promise
的rejected
状态的回调函数的参数值作为该被返回的Promise
的rejected
状态回调函数的参数值如果
then
中的回调函数返回一个未定状态(pending)的Promise
,那么then
返回Promise
的状态也是未定的,并且它的终态与那个Promise
的终态相同;同时,它变为终态时调用的回调函数参数与那个Promise
变为终态时的回调函数的参数是相同的
举例来说
1 | let promise = Promise.resolve(123).then(value => { |
then
方法返回一个新的Promise
对象,故可以使用链式操作
1 | Promise.resolve('a').then(str => { |
Promise.prototype.catch()
该方法用于指定发生错误时的回调函数,相当于.then(null, onRejected)
1 | Promise.prototype.catch(onRejected); |
onRejected
当
Promise
被rejected
时,被调用的一个函数
1 | var promise = new Promise((resolve, reject) => { |
等效于
1 | var promise = new Promise((resolve, reject) => { |
如果Promise
状态已经变成Resolved
,则再抛出错误无效
1 | var promise = new Promise((resolve, reject) => { |
Promise
对象的错误可以一直向后传递,直到被捕获
1 | var promise = new Promise((resolve, reject) => { |
Promise.prototype.finally()
finally
用于指定不管Promise
对象最后状态如何都会执行的操作,接受一个
静态方法
Promise.resolve()
Promise.resolve()
可以将现有对象转为Promise
对象
1 | Promise.resolve('hello').then(value => { |
上面的写法等价于
1 | new Promise(resolve => resolve('hello')).then(value => { |
Promise.resolve
可以接受四种参数
Promise 实例
如果参数是
Promise
实例,那么该方法不会对其做任何修改,直接返回这个实例1
2
3
4
5
6var p1 = new Promise(resolve => resolve('hello'));
Promise.resolve(p1).then(value => {
console.log(value + ' world');
})
// hello worldthenable 对象
thenable
对象是指具有then
方法的对象1
2
3
4
5
6
7
8
9
10let thenable = {
then: function (resolve, reject) {
resolve('hello');
}
};
Promise.resolve(thenable).then(value => {
console.log(value);
});
// hello不具有 then 方法的对象或者原始值
Promise.resolve
返回一个新的Promise
对象,状态为fulfilled
,参数将作为回调函数的参数值1
2
3
4
5
6
7
8
9let obj = {
a: 'hello',
b: 'world'
};
Promise.resolve(obj).then(value => {
console.log(value.a + value.b);
});
// helloworld无参数
直接返回一个
fulfilled
状态的对象
Promise.reject()
Promise.reject
方法返回一个Promise
对象,其状态为rejected
1 | Promise.reject(new Error('Error')).catch(error => { |
Promise.all()
Promise.all
用于将多个Promise
实例包装成一个新的Promise
实例
1 | Promise.all(iterable); |
iterable
是一个可遍历的对象
如果传入的参数是一个空的对象或不包含任何
Promise
对象,则返回一个fullfilled
状态的Promise
对象1
2
3
4
5
6
7
8
9
10
11
12
13Promise.all([]).then(resolve => {
console.log('resolved');
}, error => {
console.log('rejected');
});
// resolved
--------------------------------------------------------
Promise.all([1, 2, 3]).then(resolve => {
console.log('resolved');
}, error => {
console.log('rejected');
});
// resolved其它情况下,若传入的
Promise
状态都变成fulfilled
,则返回一个fulfilled
状态的Promise
,各个实例的返回值组成一个数组,作为回调函数的参数;只要一个Promise
状态为rejected
,则返回rejected
,第一个被rejected
的实例的返回值作为回调函数的参数1
2
3
4
5
6
7
8var p1 = Promise.resolve('hello'),
p2 = Promise.resolve(' '),
p3 = Promise.resolve('world');
Promise.all([p1, p2, p3]).then(value => {
console.log(value.join(''));
});
// hello world1
2
3
4
5
6
7
8
9
10var p1 = Promise.resolve('hello'),
p2 = Promise.reject(new Error('error')),
p3 = Promise.resolve('world');
Promise.all([p1, p2, p3]).then(value => {
console.log(value.join(''));
}, error => {
console.log(error);
});
// Error: error
Promise.race()
Promise.all
同样用于将多个Promise
实例包装成一个新的Promise
实例,与Promise.all
不同的是,返回的Promise
的状态取决于最先改变的实例
1 | var p1 = new Promise((resolve, reject) => { |
如果将上面p3
的时间改为20,则会报错
1 | var p1 = new Promise((resolve, reject) => { |
Promise.allSettled()
与Promise.all
类似,用于将多个Promise
实例包装成一个新的Promise
实例,但不同之处在于会返回每个实例的状态
1 | var p1 = Promise.resolve('hello'), |