3月19日观阮一峰es6 Promise笔记

207 阅读4分钟
Promise
基本概念:

promise是es6中提出的一种异步编程的解决方案。

  1. promise有三种状态,pending,fulfilled,rejected。promise的状态不受外部的影响,只有内部的异步操作的结果可以影响promise的状态。其他手段无法影响promise的状态
  2. promise的状态一旦改变就无法更改了。并且状态的变化只有两种可能。pending->fulfilled和pending->rejected。
promise的优点:

promise可以将异步操作用同步的流程表达出来,避免的回调地狱,是代码更可控,更易读。

promise的缺点:
  1. promise对象一旦建立就会立刻执行,无法取消。
  2. 当promise处于pending状态时,无法得知进展到哪一个阶段
promise基本用法

promise是一个构造函数,可以通过new生成一个promise实例

promise构造函数接受一个函数作为参数,该函数有两个参数(resolve,reject),也都是函数。这两个函数时js引擎提供的,不需要自己写。

resolve和reject函数

resolve的作用是,将promise对象的状态从pending转为fulfilled,在异步操作执行成功时调用,并将异步操作的结果作为参数,返回出去。

reject的作用是,将promise的状态从pending转为rejected,在异步操作失败时调用,并将异步操作的错误作为参数,返回出去

注:调用resolve或者reject并不能中介promise的参数函数执行

new Promise((resolve, reject) => {
  resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
});
// 2 resolve后边的console.log(2)仍然会执行
// 1

一般来说resolve以后promise的使命就结束了,因此可以使用 return来保证resolve或者reject就是promise 内最后执行的语句。

then方法和catch方法都是定义在promise的原型对象上边

then方法

promise对象可以用then方法分别指定promise对象的状态为fulfilled和rejected的回调函数。

then方法可以接受两个回调函数作为参数,第一个函数是promise对象的状态转为fulfilled时调用,第二个函数是promise对象的状态转为rejected时调用。这两个函数都是可选参数,不一定要提供。并且这两个函数都可以接受promise传出的值作为参数(创建promise对象的时候,resolve函数和reject函数传出来的值)。

then同时会返回一个新的promise对象,这也是promise实现链式调用,解决回调地狱的原因。

catch方法

catch方法是then(null,rejection)和then(undefined,rejection)的别名,用于指定发生错误时的回调函数。相对于then的第二个函数,更加推荐使用catch的使用。

注:如果没有使用catch作为发生错误时的回调函数,promise内部的错误也不会影响外部的代码

js语言遇到错误的时候,会退出进程,终止脚本运行

console.log(abc+2);//Uncaught ReferenceError: abc is not defined
    console.log(1);

但是如果promise内部出现了错误,promise会“吃掉”错误,不会退出进程,终止脚本。

const p1 = new Promise((resolve,reject)=>{
      resolve(x+2)
    })
    setTimeout(() => {
      console.log(3);
    }, 0);
    console.log(1);                           //控制台输出:1, 2, Uncaught (in promise)       setTimeout(() => {                              ReferenceError: x is not defined
      console.log(4);                                       3,4
    }, 0);
    console.log(2);                                 
  

我们可以注意到即使promise报错了,后续的log都可以执行

Promise.prototype.finally()

用于指定promise对象无论状态是什么,最后都要执行的方法,示例代码:

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
Promise.all()

将多个promise实例对象包装成一个全新的promise实例。

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

promise.all的参数可以是数组或者具有iterator接口的参数

p的状态是由参数里的promise决定的。

  1. 只有参数中的promise实例全部为fulfilled时,promise.all返回的promise实例的状态才会是fulfilled
  2. 只要参数中的promise实例有一个为rejected,那么promise.all返回的promise实例的状态就为rejected,并且第一个被rejected的实例的返回值,会传递给promise.all返回的promise实例。
Promise.race()

promise.race()方法同样是将多个promise实例对象,包装成一个新的promise实例。

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

promise.race()和promise.all()大体上相同,只是race()返回的promise实例的状态是由参数里第一个改变状态的promise对象决定的。

Promise.resolve()

将现有对象转换为promise对象,promise.resolve()起到的就是这个作用。

Promise.resolve('foo')<========> new Promise(resolve=>{resolve('foo')})

注:当Promise.resolve()中不传递参数或者参数不具备then()方法的对象的时候,那么会立刻返回一个状态为resolved的promise实例对象,这个过程是同步的。并且将紧跟着的then方法放到微任务队列当中。然后执行下一段同步代码
Promise.reject()

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected

const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))
​
p.then(null, function (s) {
  console.log(s)
});
// 出错了

\