Promise入门和相关方法的使用| 8月更文挑战

275 阅读5分钟

一、Promise的作用

Promise是用来解决异步编程问题,使用同步操作的形式表达异步操作的流程,解决了传统异步操作中回调层层嵌套的问题。

二、Promise的状态

  1. promise包含三种状态:pending(进行中)、fulfilled(成功)、rejected(失败)。
  2. 状态改变只有两种可能:
  • pending->fulfilled
  • pending->rejected
  1. 状态一旦改变,就不会再变。

三、Promise的基本使用

  1. Promise接收一个回调函数,该回调函数接受两个参数,resolve和reject。
  2. resolve和reject两个函数是Promise内部实现的。
  • resolve中将pending状态变为fulfilled状态,在异步操作成功时调用,将异步操作的结果作为参数传递出去。
  • reject中将pending状态变为rejected状态,在异步操作失败时调用,将异步操作的报错作为参数传递出去。
  1. Promise实例生成后,可用then方法来指定resolve和reject的回调函数。
let promise = new Promise(function(resolve, reject) {
  let a = 1;
  if(a==1) {
    resolve(1);
  } else {
    reject(2);
  }
}).then(function(val) {
  console.log(val);
},function(err) {
  console.log(err);
});

四、Promise的执行顺序

Promise的执行顺序:

  1. Promise在新建时会立即执行;
  2. 执行所有同步任务执行;
  3. 执行then方法指定的回调函数。 例子:
let promise = new Promise(function(resolve, reject) {
  let a = 1;
  if(a==1) {
    resolve(1);
  } else {
    reject(2);
  }
  console.log(1);
}).then(function(val) {
  console.log(2);
},function(err) {
  console.log(err);
});
console.log(3);
// 1
// 3
// 2

五、异步操作的结果是返回另一个异步操作

当异步操作p2的resolve的参数为另一个异步操作p1时,p2会等待p1返回结果,p1的状态决定p2的状态。 例子:

let p1 = new Promise(function(resolve, reject) {
  reject(new Error('fail'));
})
let p2 = new Promise(function(resolve, reject) {
  resolve(p1);
})
console.log(p2);

执行结果:

微信图片_20210731172535.png

六、Promise.prototype.then()

then(resovleCallback, rejectCallback):指定resolve和reject的回调函数,返回一个新的Promise实例。

例子:

let p = new Promise(function(resolve, reject) {
  resolve(1);
}).then(function(val) {
  console.log(val)catch
  return 2;
}).then(function(val) {
  console.log(val)
  return 3;
})
console.log(p);

执行结果:

image.png

七、Promise.prototype.catch()

catch(rejectCallback):指定发生错误时的回调函数,可以捕获到前面如何一个Promise实例发生的错误。

例子:

let p = new Promise(function(resolve, reject) {
  reject(new Error('失败'))
}).then(function(val) {
  console.log(val)
}).catch(function(err) {
  console.log(err);
})

执行结果:

image.png

注意:如果没有使用catch方法,浏览器会报错,但是不会退出进程、终止脚本执行,即后面的代码仍然正常执行。

例子:

let p = new Promise(function(resolve, reject) {
  reject(new Error('失败'))
}).then(function(val) {
  console.log(val)
})
setTimeout(function() {
  console.log(1)
}, 1000);

执行结果:

image.png

八、Promise.prototype.finally()

finally():无论promise最后的状态如何,都会执行finally方法指定的回调函数。 例子:

let p = new Promise(function(resolve, reject) {
  resolve(1)
}).then(function(val) {
  console.log(val)
}).finally(function() {
  console.log(123)
})

执行结果:

image.png

九、Promise.resolve()

1.参数

  • 若接收的参数为Promise实例,则返回该实例;
  • 若接收的参数不为Promise实例,则转化为Promise实例,如果该参数原本带有then方法,则转化后立即执行then方法。 2.返回一个新的Promise实例。

例子:

const obj = {
  then: function(resolve, reject) {
    resolve(111);
  }
}
const p = Promise.resolve(obj);
console.log(p);

执行结果:

image.png

十、Promise.reject()

  1. 返回一个新的状态为rejected的Promise实例。
  2. 参数将作为后续方法的参数。

例子:

const p = Promise.reject('失败');
p.catch(function(err)  {
  console.log(err);
})
console.log(p);

执行结果:

image.png

十一、Promise.all()

all(arr): 接收一个数组或其他具有Iterator 接口的数据,当数组中的元素不为Promise实例时,自动调用Promise.resolve()将其转化为Promise实例。 例子:

const p = Promise.all([p1, p2, p3]);
  1. p的状态由p1,p2,p3决定:
  • 当p1,p2,p3的状态都为fulfilled时,p才为fulfilled, p1,p2,p3的返回值组成数组传递给p的回调函数。
  • 当p1,p2,p3中有一个状态为rejected时,p为rejected,第一个rejected的返回值传递给p的回调函数。

2.catch的使用:

  • 当p1,p2,p3中没有设置catch方法时,若出现错误,会使用p中的catch方法。
  • 若设置了catch方法,则若出现错误,会被他们自身的catch捕获,执行完成后,返回一个新的Promise实例给到p的回调函数,所以p的catch并不会被触发,p的状态为fulfilled。 例子:
const p1 = new Promise(function(resolve, reject) {
  resolve(1);
})
const p2 = new Promise(function(resolve, reject) {
  reject(new Error('失败'));
}).catch(function(err) {
  console.log(err);
});
const p = Promise.all([p1,p2]).catch(function(err) {
  console.log(err);
});
console.log(p);

执行结果:

image.png

十二、Promise.race()

race(array):接收参数与all(array)一样,接收一个数组或其他具有Iterator 接口的数据,当数组中的元素不为Promise实例时,自动调用Promise.resolve()将其转化为Promise实例。

例子:

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

1.p的状态: p1,p2,p3哪个先更改状态时,p就随之更改状态,先更改状态的实例的返回值传递给p的回调函数。 例子:

const p1 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve(1);
  }, 200)
})
const p2 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    reject(new Error('失败'))
  }, 100)
})
const p = Promise.race([p1,p2]);
p.then(function(val) {
  console.log(val)
}).catch(function(err) {
  console.log(err);
});
console.log(p);

执行结果:

image.png

十三、Promise.allSettled()

allSettled():接收参数与all(array)一样,接收一个数组或其他具有Iterator 接口的数据,当数组中的元素不为Promise实例时,自动调用Promise.resolve()将其转化为Promise实例。

例子:

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

1.p的状态: 当p1,p2,p3都返回结果时,无论返回的状态是fulfilled还是reject,p的状态都为fulfilled,不会变成rejected。 p的回调函数接收到的是参数实例返回的状态组成的数组。

  • 当参数实例返回的状态是fulfilled时,传递的返回值是{status:'fulfilled', value:resolve值}
  • 当参数实例返回的状态是fulfilled时,传递的返回值是{status:'rejected', reason:失败原因}

例子:

const p1 = new Promise(function(resolve, reject) {
  resolve(1);
})
const p2 = new Promise(function(resolve, reject) {
  reject(new Error('失败'))
})
const p = Promise.allSettled([p1,p2]);
console.log(p);

执行结果:

image.png

十四、Promise.any()

any():接收参数与all(array)一样,接收一个数组或其他具有Iterator 接口的数据,当数组中的元素不为Promise实例时,自动调用Promise.resolve()将其转化为Promise实例。 例子:

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

1.p的状态:

  • 当p1,p2,p3有一个返回fulfilled状态时,p的状态就为fulfilled,该参数实例的返回值传给p的回调函数;
  • 当p1,p2,p3的状态都为rejected时,p的状态才为rejected,所有报错的返回值组成数组传递给p的回调函数。 例子:
const p1 = new Promise(function(resolve, reject) {
  reject(new Error('失败1'))
})
const p2 = new Promise(function(resolve, reject) {
  reject(new Error('失败'))
})
const p = Promise.any([p1,p2]);
console.log(p);

执行结果:

image.png