- 定义
Promise里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
特点:1.对象的状态不受外界影响;
2.一旦状态改变就不会再变,且通过添加回调函数可以得到该结果。
状态:1.pending(进行中)--> fulfilled(已成功)
2.pending(进行中)--> rejected(已失败)
- 基本用法
1.resolved:“未完成”-->“成功”
rejected:“未完成”-->“失败”
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done');
});}
timeout(3000).then((value) => {
console.log(value);});//执行后,会在3000ms后打印出done
2.promise新建后将会立即执行,而then方法指定的回调函数,要在当前脚本所有同步任务执行完才会执行。
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();});
promise.then(function() {
console.log('resolved.');});
console.log('Hi!');
// Promise
// Hi!
// resolved
3.如果p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是resolved或者rejected,那么p2的回调函数将会立刻执行。
const p1 = new Promise(function (resolve, reject) {
// ...});
const p2 = new Promise(function (resolve, reject) {
// ...
resolve(p1);})
例:
const p1 = new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('fail')), 3000)})
const p2 = new Promise(function (resolve, reject) {
setTimeout(() => resolve(p1), 1000)})
p2
.then(result => console.log(result))
.catch(error => console.log(error))// Error: fail
p1是一个 Promise,3 秒之后变为rejected。p2的状态在 1 秒之后改变,resolve方法返回的是p1。由于p2返回的是另一个 Promise,导致p2自己的状态无效了,由p1的状态决定p2的状态。所以,后面的then语句都变成针对后者(p1)。又过了 2 秒,p1变为rejected,导致触发catch方法指定的回调函数。
4.调用resolve或reject以后,Promise 的使命就完成了,后继操作应该放到then方法里面,而不应该直接写在resolve或reject的后面。所以,最好在它们前面加上return语句,这样就不会有意外。
new Promise((resolve, reject) => {
return resolve(1);
// 后面的语句不会执行
console.log(2);})
*******************************************************
new Promise((resolve, reject) => {
resolve(1);
console.log(2);}).then(r => {
console.log(r);});// 2// 1 //resolved 的 Promise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。
- Promise.prototype.catch()
1.当返回一个 Promise 对象,如果该对象状态变为resolved,则会调用then()方法指定的回调函数;如果异步操作抛出错误,状态就会变为rejected,就会调用catch()方法指定的回调函数,处理这个错误。另外,then()方法指定的回调函数,如果运行中抛出错误,也会被catch()方法捕获。
2.Promise 在resolve语句后面,再抛出错误,不会被捕获,等于没有抛出。因为 Promise 的状态一旦改变,就永久保持该状态,不会再变了。
const promise = new Promise(function(resolve, reject) {
resolve('ok');
throw new Error('test');});
promise
.then(function(value) { console.log(value) })
.catch(function(error) { console.log(error) });// ok
3.catch()方法返回的还是一个 Promise 对象,因此后面还可以接着调用then()方法。
Promise.resolve()
catch(function(error) {console.log('oh no', error);})
.then(function() {console.log('carry on');});
// oh no [ReferenceError: x is not defined]
// carry on
没有报错,跳过了catch()方法,直接执行后面的then()方法。
Promise.resolve().catch(function(error) {
console.log('oh no', error);}).then(function() {
console.log('carry on');});// carry on
- Promise.all(),Promise.any(),Promise.race()
将多个Promise实例包装成一个新的Promise实例。其中:(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
注意:如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。如果它没有自己的catch方法,就会调用Promise.all()的catch方法。
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: 报错了]
********************************************************************
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: 报错了
Promise.any()只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;只有参数都变成rejected状态,包装实例才会变成rejected状态。
Promise.race()只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;只要有一个变成rejected状态,包装实例就会变成rejected状态。
- promise.resolve()
将现有对象转为 Promise 对象。
setTimeout(function () {
console.log('three');}, 0);
Promise.resolve().then(function () {
console.log('two');});
console.log('one');
// one
// two
// three
setTimeout(fn, 0)在下一轮“事件循环”开始时执行,Promise.resolve()在本轮“事件循环”结束时执行,console.log('one')则是立即执行,因此最先输出。