【用法】
- executor 函数在Promise构造函数执行时同步执行,executor 内部通常会执行一些异步操作,一旦完成,可以调用resolve函数来将promise状态改成fulfilled,或者在发生错误时将它的状态改为rejected。
- 因为 Promise.prototype.then 和 Promise.prototype.catch 方法返回promise 对象, 所以它们可以被链式调用。
- 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。
基本句法1
2
3
4
5
6
7
let promise = new Promise( ()=> (resolve, reject) {...} /* executor */ );
promise.then((value)=> {
// resolved的回调
}, (error)=> {
// rejected的回调
});
例11
2
3
4
5
6
new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'done');
}).then((value)=>{
console.log(value); //两秒后打印 done
});
例2(ajax)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26const getJSON = (url)=> {
return new Promise((resolve, reject)=>{
const handler = () => {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
});
};
getJSON("/posts.json").then((res) => {
console.log('success:', res);
}, (error) => {
console.error('error', error);
});
Promise.prototype.then()
then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。1
2
3
4
5
6getJSON("/post/1.json").then(
post => getJSON(post.URL)
).then(
success => console.log("resolved: ", success),
error => console.log("rejected: ", error)
);
Promise.prototype.catch()
catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。
Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止1
2
3
4
5
6getJSON('/posts.json').then((posts) => {
}).catch(function(error) {
// 处理 getJSON 和 前一个回调函数运行时发生的错误
console.log('发生错误!', error);
});
Promise.all(iterable)
- Promise.all 方法常被用于处理多个promise对象的状态集合。
- Promise.all 等待所有代码的完成(或第一个代码的失败)。
- 如果iterable包含非promise值,则它们将被忽略,但仍然计入返回的promise。
- 如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。
这些可能一时很难体会,看例子更直观:
1 | let p1 = Promise.resolve(1); |
Promise.race(iterable)
当iterable之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给race()回调函数。
Promise.resolve()
将现有对象转为 Promise 对象
- 参数是一个Promise实例,原封不动地返回这个实例。
- 参数是一个thenable对象,具有then方法的对象,转为Promise对象后就立即执行thenable对象的then方法。
- 参数不是具有then方法的对象,或非对象,返回新的Promise对象,状态为resolved。
- 不带参数,如果只为了异步
1
2
3
4
5
6
7
8
9
10let thenable = {
then: function(resolve, reject) {
resolve(0);
}
};
let p1 = Promise.resolve(thenable);
p1.then((value) => {
console.log(value); // 0
});
1 | // 不带参数类似异步 |
Promise.reject()
也会返回一个新的Promise实例,reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数
【扩展】
done()
done方法,总是处于回调链的尾端,保证抛出任何可能出现的错误。1
2
3
4
5
6
7
8
9
10
11
12
13Promise.prototype.done = (onFulfilled, onRejected) => {
this.then(onFulfilled, onRejected)
.catch((reason) => {
// 抛出一个全局错误
setTimeout(() => { throw reason }, 0);
});
};
textFn()
.then(f1)
.catch(r1)
.then(f2)
.done();
finally()
finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。1
2
3
4
5
6
7Promise.prototype.finally = (callback) => {
let p = this.constructor;
return this.then(
value => p.resolve(callback()).then(() => value),
reason => p.resolve(callback()).then(() => { throw reason })
);
};