Promise 对象的明白

Promise 寄义

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事宜——更合理和更壮大。它由社区最早提出和完成,ES6 将其写进了言语规范,一致了用法,原生供应了 Promise 对象。

所谓 Promise,简单说就是一个容器,内里保存着某个将来才会完毕的事宜(通常是一个异步操纵)的效果。从语法上说,Promise 是一个对象,从它能够猎取异步操纵的音讯。Promise 供应一致的 API,种种异步操纵都能够用一样的要领举行处置惩罚。

Promise 对象有以下两个特性:

  • 对象的状况不受外界影响。有三种状况,分别为 pending(举行中)、fulfilled(已胜利)和 rejected(已失利)。
  • 一旦状况转变,就不会再变,任何时候都能够获得这个效果。状况转变只需两种能够:从 pending 变成 fulfilled 和从 pending 变成 rejected。

运用 Promise 对象的优点在于:

  • 能够将异步操纵以同步操纵的流程表达出来,避免了层层嵌套的回调函数。
  • Promise 对象供应一致的接口,使得掌握异步操纵越发轻易。

Promise 瑕玷:

  • 没法作废 Promise,一旦新建它就会马上实行,没法半途作废。
  • 假如不设置回调函数,Promise 内部抛出的毛病,不会回响反映到外部。
  • 当处于 pending 状况时,没法得知现在希望到哪个阶段(刚刚开始照样行将完成)。

基础用法

ES6 划定,Promise 对象是一个组织函数,用来天生 Promise 实例。

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const num = Math.random();

    if (num > 0.5) {
      resolve(num);
    } else {
      reject(num);
    }
  }, 500);
});

promise.then(
  res => {
    console.log("胜利:" + res);
  },
  err => {
    console.log("失利:" + err);
  }
);

Promise 组织函数接收一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。它们是两个函数,由 JavaScript 引擎供应,不必本身布置。

  • resolve 函数的作用:将 Promise 对象的状况从“未完成(pending)”变成“胜利(resolved)”,在异步操纵胜利时挪用,并将异步操纵的效果作为参数通报出去。
  • reject 函数的作用:将 Promise 对象的状况从“未完成(pending)”变成“失利(rejected)”在异步操纵失利时挪用,并将异步操纵报出的毛病,作为参数通报出去。
  • then 要领作用:接收两个回调函数作为参数。第一个回调函数是 Promise 对象的状况变成 resolved 时挪用,第二个回调函数是 Promise 对象的状况变成 rejected 时挪用。第二个函数可选,不一定要供应,也能够将第二个函数作为 catch 要领的参数。
  • catch 要领作用:用于指定发作毛病时的回调函数。Promise 对象异步操纵抛出毛病,状况就会变成 rejected,就会挪用 catch 要领指定的回调函数处置惩罚这个毛病。别的,then 要领指定的回调函数,假如运转中抛出毛病,也会被 catch 要领捕捉。
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const num = Math.random();

    if (num > 0.5) {
      resolve(num);
    } else {
      reject(num);
    }
  }, 500);
});

promise
  .then(res => {
    console.log("胜利:" + res);
  })
  .catch(err => {
    console.log("失利:" + err);
  });

promise
  .then(res => {
    console.log("胜利:" + res);
    throw new Error("test");
  })
  .catch(err => {
    // num > 0.5时打印 "失利:Error: test"
    console.log("失利:" + err);
  });

Promise 实行递次

Promise 新建后马上实行,then 要领指定的回调函数,将在当前剧本一切同步使命实行完才会实行,catch 同理。

挪用 resolve 或 reject 并不会闭幕 Promise 的参数函数的实行。

const promise = new Promise((resolve, reject) => {
  console.log("我是第一个实行的");
  resolve();
});

promise.then(res => {
  console.log("我是第三个实行的");
});

console.log("我是第二个实行的");

resolve 函数和 reject 函数的参数

reject 函数的参数通常是 Error 对象的实例,示意抛出的毛病;resolve 函数的参数除了一般的值之外,还多是另一个 Promise 实例。

假如一个 Promise(P2) 的 resolve 参数是另一个 Promise(P1),此时 P1 的状况就会传给 P2,P1 的状况决议了 P2 的状况,P1 的状况转变,P2 的回调函数才会实行。

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 要领指定的回调函数。

Promise 链式挪用

then 要领能够返回一个新的 Promise 实例(注重,不是本来谁人 Promise 实例)。因而能够采纳链式写法,即 then 要领背面再挪用另一个 then 要领。

const promise = new Promise((resolve, reject) => {
  resolve("promise");
})
  .then(res => {
    console.log(res); // promise
    return "promise1";
  })
  .then(res => {
    console.log(res); // promise1
    return "promise2";
  })
  .then(res => {
    console.log(res); // promise2
  });

注重:只需一个 Promise 中抛出毛病,将实行 catch 要领,then 链停止。

const promise = new Promise((resolve, reject) => {
  resolve("promise");
})
  .then(res => {
    console.log(res); // promise
    throw new Error("中断");
    return "promise1";
  })
  .then(res => {
    console.log(res);
    return "promise2";
  })
  .then(res => {
    console.log(res);
  })
  .catch(err => {
    console.log(err); // Error: 中断
  });

主动停止 then 链,经由过程 catch 要领来中断 promise chain

const promise = new Promise((resolve, reject) => {
  resolve("promise");
})
  .then(res => {
    console.log(res); // promise
    return Promise.reject({
      notRealPromiseException: true
    });
  })
  .then(res => {
    console.log(res);
    return "promise2";
  })
  .then(res => {
    console.log(res);
  })
  .catch(err => {
    if (err.notRealPromiseException) {
      return true;
    }
    console.log(err);
  });

Promise.prototype.finally()

finally 要领用于指定不论 Promise 对象末了状况怎样,都邑实行的操纵。该要领是 ES2018 引入规范的。

finally 本质上是 then 要领的惯例,不接收任何参数,不依赖于 Promise 的实行效果

promise.finally(() => {
  // 语句
});

// 等同于
promise.then(
  result => {
    // 语句
    return result;
  },
  error => {
    // 语句
    throw error;
  }
);

Promise.all()

Promise.all 要领用于将多个 Promise 实例,包装成一个新的 Promise 实例。

const promise = Promise.all([promise1, promise2, promise3])

Promise.all 要领接收一个数组作为参数,promise、pro 米色、promise3 都是 Promise 实例,假如不是,就会先挪用下面讲到的 Promise.resolve 要领,将参数转为 Promise 实例,再进一步处置惩罚。(Promise.all 要领的参数能够不是数组,但必需具有 Iterator 接口,且返回的每一个成员都是 Promise 实例。相识 Iterator 接口

promise 的状况由 promise1、promise2、promise3 决议,分红两种状况。

  • 只需 promise1、promise2、promise3 的状况都变成 fulfilled,p 的状况才会变成 fulfilled,此时 promise1、promise2、promise3 的返回值构成一个数组,通报给 p 的回调函数。
  • 只需 promise1、promise2、promise3 当中有一个被 rejected,promise 的状况就变成 rejected,此时第一个被 reject 的实例的返回值,会通报给 promise 的回调函数。
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: 报错了]

上面代码中,p1 会 resolved,p2 首先会 rejected,然则 p2 有本身的 catch 要领,该要领返回的是一个新的 Promise 实例,p2 指向的实际上是这个实例。该实例实行完 catch 要领后,也会变成 resolved,致使 Promise.all()要领参数内里的两个实例都邑 resolved,因而会挪用 then 要领指定的回调函数,而不会挪用 catch 要领指定的回调函数。

假如 p2 没有本身的 catch 要领,就会挪用 Promise.all()的 catch 要领。

Promise.race()

Promise.race 要领一样是将多个 Promise 实例,包装成一个新的 Promise 实例。

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

只需 p1、p2、p3 当中有一个实例领先转变状况,p 的状况就随着转变。谁人领先转变的 Promise 实例的返回值,就通报给 p 的回调函数。

Promise.race 要领的参数与 Promise.all 要领一样,假如不是 Promise 实例,就会先挪用下面讲到的 Promise.resolve 要领,将参数转为 Promise 实例,再进一步处置惩罚。

Promise.resolve()

将现有对象转化为 Promise 对象。

const promise = Promise.resolve(‘Hello world’)

  • 参数是 Promise 实例,该要领不做任何转变。
  • 参数是一个 thenable 对象,先将对象转为 Promise 对象,然后马上实行 thenable 要领。相当于将 thenable 对象中的 then 要领处置惩罚的值作为参数传给 promise then 要领。
let thenObj = {
  then(resolve, reject) {
    resolve("Hello");
  }
};

const promise = Promise.resolve(thenObj);
promise.then(res => {
  console.log(res); // Hello
});
  • 参数不是具有 then 要领的对象,或基础就不是对象,则 Promise.resolve 要领返回一个新的 Promise 对象,状况为 resolved。

Promise.reject()

Promise.reject(reason)要领也会返回一个新的 Promise 实例,该实例的状况为 rejected。

    原文作者:欧西里斯的天秤
    原文地址: https://segmentfault.com/a/1190000018769508
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞