Promise

161 阅读4分钟

一:什么是Promise

Promise是一个对象,它代表一个一步操作的最终完成或者是失败。它的thencatchfinally方法会返回一个新的Promise,这就是Promise很棒的一点---链式调用(chaining)

二:Promise的三种状态

pending:进行中 fulfilled:已成功 rejected:已失败

1、一旦状态改变,就不能再发生变化

2、Promise对象的状态的改变,只能有两种:

pending ===>  fulfilled
pending ===>  rejected

三:Promise基本用法

创造一个Promise实例:

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

Promise的两个参数:resolve和reject(两个函数)

resolve()

Promise的状态从未完成(pending)变为成功(resolve),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;

reject()

Promise的状态从未完成(pending)变为失败(rejected),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。

四:then 和 catch

const flag = 1;

const p = new Promise((resolve, reject) => {
  if(flag) {
    resolve(flag);
  } else {
    console.log('Error');
    reject();
  }
});

p.then(res => {
  if(res) {
    console.log('res', res);
  }
}).catch(err => {
  console.log('Promise is rejected now !!!', err);
}).finally(() => {
  console.log('I am finally');
});

// 输出结果:
// res 1
// I am finally

上面代码中,p返回一个Promise对象,当flag为1时,状态就变为resolved,则会调用.then()方法指定的回调函数。

下述代码中,当flag为0时,状态就会变成rejected,则会调用.catch()方法指定的回调函数。

const flag = 0;

const p = new Promise((resolve, reject) => {
  if(flag) {
    resolve(flag);
  } else {
    console.log('Error');
    reject();
  }
});

p.then(res => {
  if(res) {
    console.log('res', res);
  }
}).catch(err => {
  console.log('Promise is rejected now !!!', err);
}).finally(() => {
  console.log('I am finally');
});

// 输出结果:
// Error
// Promise is rejected now !!! undefined
// I am finally

上述两段代码,不管Promise的状态变成resolved还是rejected,finally()指定的回调函数都会被调用。

1、.then.catch都会返回一个新的Promise

2、catch不管被连接到哪里,都能捕获上层未捕获过的错误。

3、.then.catchreturn一个error对象并不会抛出错误,所以不会被后续的.catch捕获。

4、.then.catch返回的值不能是Promise,不然会造成死循环

5、.then方法是可以接收两个参数的,第一个是处理成功的函数,第二个是处理失败的函数,在某些时候可以认为catch.then的第二个参数的简单写法。

// p是一个Promise
p.then()

五:finally

1、.finally()方法不管Promise对象最后的状态是什么,都会执行。

2、.finally()方法不接收任何参数,也就是说在finally中不知道Promise最终的状态是resolved还是rejected

六:all和race

1. Promise.all()

Promise.all()方法用于将多个Promise实例,包装成一个新的Promise实例。

const p = Promise.all([p1, p2, p3]);
  • 状态变化

(1)只有所有状态都变成fulfilledp的状态才会变成fulfilledp1p2p3的返回值组成一个数组,传递给p的回调函数。

(2)只要其中有一个被rejectedp的状态就会变成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('I am rejected, but .then and .catch will return a new Promise!!');
}).then(result => result).catch(e => e);

Promise.all([p1, p2]).then(result => console.log(result)).catch(e => e);

// 输出结果
// ['hello','I am rejected, but .then and .catch will return a new Promise']
// p1:resolved, p2:reject,但是.catch返回了一个新的Promise,最后也会变成resolved,所以all的.then方法指定的回调函数会被调用

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

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

const p2 = new Promise((resolve, reject) => {
  throw new Error('I am rejected, but .catch is not exist!!');
})
.then(result => result);

Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));

// 输出结果
// Error: I am rejected, but .catch is not exist!!
// p2没有自己的catch,所以p2的错误会被Promise.all的catch捕获到

2.Promise.race()

Promise.race()的语法和all的差不多,都是将多Promise实例包装成一个新的Promise实例。

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

p1p2p3之中只要有一个实例率先改变状态,p的状态就会跟着变化,并且会吧率先改变的返回值传递给p的毁掉函数

七:Promise执行顺序问题

Promise新建之后就会立即执行

const promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});

promise.then(function() {
  console.log('resolved.');
});

console.log('Hi!');

// Promise     Promise新建后立即执行
// Hi!         先执行同步任务
// resolved
Promise新建后立即执行,首先输出Promise,then方法指定的回调函数,将在当前脚本所有同步任务执行完成之后才会执行,所有resolved最后输出