Promise 对象本质上表示的是一系列操作的中间状态,或者说是未来某时刻一个操作完成或失败后返回的结果。 Promise并不保证操作在何时完成并返回结果,但是保证在当前操作成功后执行你对操作结果的处理代码,或在操作失败后,优雅地处理操作失败的情况。 ——-MDN

Promise是什么?

根据开发者工具打印出来就知道
image.png

由此可见,Promise是JS一个内置对象了。

Promise 的用途

  • Promise是目前前端解决异步问题的统一方案,为异步操作提供统一接口。
  • 与之进行交互的方式主要是 then 方法,该方法注册了两个回调函数,用于接收 promise 的终值或本 promise 不能执行的原因。
  • Promise 用于避免回调地域,让代码看起来更同步。

如何创建一个 new Promise

  • promise 对象是由关键字new及其构造函数来创建的。
  • 该函数构造会把一个叫做“处理器函数”(executor function)的函数作为它的参数。
  • 这个“处理器函数”接受两个函数 —— resolvereject —— 作为其参数。
  • 当异步任务顺利完成且返回结果值时,会调用 resolve 函数;
  • 而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject 函数。

    1. const promise = new Promise((resolve, reject) => {
    2. if(/*异步操作成功*/){
    3. resolve(value)
    4. } else {
    5. reject(error)
    6. }
    7. });

    如何使用 Promise.prototype.then

  • then() 方法返回一个 Promise

  • 它最多需要有两个参数:Promise 的成功和失败情况的回调函数。

语法:

  1. Promise.prototype.then((value) => {
  2. // Promise状态变为成功时回调的函数
  3. }, (reason) => {
  4. // Promise状态变为失败时回调的函数
  5. })

以上面的“如何创建一个new promise”的代码作为使用方法:

  1. promise.then((Message) => {
  2. //Message的值是上面调用resolve(...)方法传入的值.
  3. //Message参数不一定非要是字符串类型
  4. console.log("成功" + Message);
  5. },(Message) => {
  6. console.log("成功" + Message);
  7. });

完成使用例子:

  1. function timeout(ms){
  2. return new Promise((resolve, reject) => {
  3. setTimeout(resolve, ms, 'done');
  4. });
  5. }
  6. timeout(100).then((value) => {
  7. console.log(value)
  8. })

如何使用 Promise.all

  • **Promise.all(iterable)** 方法返回一个 Promise 实例
  • 此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve)
  • 如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败 promise 的结果。

语法:

  1. Promise.all(iterable);//iterable是一个可迭代对象,如 Array 或 String。

作用:此方法在集合多个 promise 的返回结果时很有用。

使用:

  1. let p1 = Promise.resolve(3);
  2. let p2 = 1337;
  3. let p3 = new Promise((resolve, reject) => {
  4. setTimeout(resolve, 100, 'foo');
  5. })
  6. Promise.all([p1,p2,p3]).then(values => {
  7. console.log(values);//[3, 1337, "foo"]
  8. })

即使参数里面包含非 promise 值,这些值将被忽略,但依然被放在返回数组中:

  1. var p = Promise.all([1,2,3]);
  2. var p2 = Promise.all([1,2,3, Promise.resolve(444)]);
  3. var p3 = Promise.all([1,2,3, Promise.reject(555)]);
  4. setTimeout(() => {
  5. console.log(p);
  6. console.log(p2);
  7. console.log(p3);
  8. });
  9. // logs
  10. // Promise { <state>: "fulfilled", <value>: Array[3] }
  11. // Promise { <state>: "fulfilled", <value>: Array[4] }
  12. // Promise { <state>: "rejected", <reason>: 555 }

如何使用 Promise.race

**Promise.race(iterable)** 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

  1. var p1 = new Promise(function(resolve, reject) {
  2. setTimeout(resolve, 500, "one");
  3. });
  4. var p2 = new Promise(function(resolve, reject) {
  5. setTimeout(resolve, 100, "two");
  6. });
  7. Promise.race([p1, p2]).then(function(value) {
  8. console.log(value); // "two"
  9. // 两个都完成,但 p2 更快
  10. });
  1. var p3 = new Promise(function(resolve, reject) {
  2. setTimeout(resolve, 100, "three");
  3. });
  4. var p4 = new Promise(function(resolve, reject) {
  5. setTimeout(reject, 500, "four");
  6. });
  7. Promise.race([p3, p4]).then(function(value) {
  8. console.log(value); // "three"
  9. // p3 更快,所以它完成了
  10. }, function(reason) {
  11. // 未被调用
  12. });
  1. var p5 = new Promise(function(resolve, reject) {
  2. setTimeout(resolve, 500, "five");
  3. });
  4. var p6 = new Promise(function(resolve, reject) {
  5. setTimeout(reject, 100, "six");
  6. });
  7. Promise.race([p5, p6]).then(function(value) {
  8. // 未被调用
  9. }, function(reason) {
  10. console.log(reason); // "six"
  11. // p6 更快,所以它失败了
  12. });

如何使用Promise.prototype.catch()

例子:

  1. timeout(100).then((value) => {
  2. console.log(value)
  3. }).catch((error)=>{
  4. console.log('发生错误!', error);
  5. })
  6. //写法与下面相同作用
  7. timeout(100).then((value) => {
  8. console.log(value)
  9. }, ((err) => {
  10. console.log(err)
  11. })

上面代码中,timeout(100) 会返回一个 Promise 对象,如果该对象状态变为 resolved, 则会调用 then()方法指定的回调函数;反之,如果异步操作抛出错误,状态就会变成 rejected ,就会调用 catch() 方法制定的回调函数。或是运行中发生错误,catch()会捕获该错误。

建议使用第一种写法,因为第一种写法可以捕获前面then() 方法执行中的错误,前面有多少个then(),也就除了多少个错误,同时更接近同步的写法(try/catch)。因此建议使用第一种写法。而不是then的第二个参数.

Promise.protoytpe.finally()

finally()方法用于不管 Promise对象最后状态如何,都会执行的操作。

  1. promise
  2. .then(result => {...})
  3. .catch(error => {...})
  4. .finally(() => {...}) //不管前面代码如何,最后这一行都会执行!

【资料来源】 MDN Promise JavaScript Promise:简介 优雅的异步处理 【翻译】Promises/A+规范