ES6入门之Promise对象

1. Promise 的含义

Promise 是异步编程的一种解决方案,比传统的解决方案--回调函数和事件更合理、更强大。编程

1.1 什么是Promise

简单来讲就是一个容器,里面保存着某个将来才会结束的事件(也就是异步操做)的结果。从语法上来说,Promise是一个对象,从它能够获取异步操做的消息,它提供统一的API,各类异步操做均可以用一样的方法进行处理。数组

Promise有两个特色:

1.1.一、对象的状态不受外界影响。Promise对象表明一个异步操做,有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。只有异步操做的结果,能够决定当前是哪种状态、任何其余操做都没法改版这个状态。promise

1.1.二、一旦状态改版,就不会再变,任什么时候候均可以获得这个结果。Promise对象的状态改变,只存在两种可能:从 pending 变为 fulfilled 和 从 pending 变为 rejeced。只要这两种状况发生,状态就终止,不会再变了并一直保持这个结果。这时就称为 resolved(已定型)。若是改版已经发生了,即便再对Promise对象添加回调函数,也会当即获得这个结果。若是你错过了再想去监听,是得不到结果的。bash

1.1.三、有了Promise对象,就能够将异步操做以同步操做的流程显示出来,这样就避免了层层嵌套的回调函数。Promise对象提供统一的接口,使得控制异步操做更加容易。异步

1.1.四、Promise也有一些缺点,就是没法取消 Promise,一旦创建就会当即执行,没法中途取消。若是不设置回调函数,Promise内部抛出的错误不会反应到外部。另外若是处于 pending 状态时,是没法知道如今到了哪个阶段。异步编程

2. 基本用法

Promise对象是一个构造函数,用来生成Promise实例函数

const promise = new Promise((reolve, reject) => {
    if (// 异步操做成功) {
        resolve(val)
    }else{
        reject(val)
    }
})
复制代码

Promise 构造函数接受一个函数做为参数,该函数的两个参数分别是 resolve 和 reject。ui

resolve:,将Promise对象的状态从『未完成』变为『成功』(pending => resolved),在异步操做成功时调用,并将异步操做的结果做为参数传递出去。spa

reject:将Promise对象的状态从『未完成』变为『失败』(pending => rejected),在异步操做失败时调用,并将异步操做的结果做为参数传递出去。prototype

Promise 实例生成之后,能够用 then 方法分别指定 resolved 状态和 rejected 状态的回调函数。

promise.then((val) => {
    // success
},(err) => {
    // failure
})
复制代码

then方法能够接受两个回调函数做为参数。(第二个函数可选,这两个函数都接受Promise对象传出的值做为参数)

一、第一个回调函数在Promise对象的状态变为『resolved』时调用。

二、第二个回调函数在Promise对象的状态变为『rejected』时调用。

实例:

function timeout(ms) {
    retrun new Promise((resolve, reject) => {
        setTimeout(resolve, ms, 'done')
    })
}

timeout(100)
.then((v) => {
    console.log(v)
})
复制代码

上面代码中,timeout方法返回一个Promise实例,表示一段时间之后才会发生的结果,过了 ms时间后,Promise状态变为『resolved』而后就会触发then方法绑定的回调函数。

Promise 创建后就会当即执行

let promise = new Promise((resolve, reject) => {
    console.log('Promise')
    resolve()
})

promise
.then(() => {
    console.log('resolved')
})

console.log('hh')

// Promise
// hh
// resolved
复制代码

Promise创建后当即执行,首先输出 「Promise」而后执行promise 的then函数,而后首先执行同步任务 输出 hh 在执行 then方法的回调函数输出resolved

若是调用 resolve 函数和 reject 函数时带有参数,那么它们的参数会被传递给回调函数。reject函数的参数一般是Error对象的实例,表示抛出的错误。resolve函数的参数除了正常的值之外,还有多是一个Promise实例。resolve实在成功的时候调用,reject是在失败的时候调用。

const p1 = new Promise(function (resolve, reject) {
  // ...
});

const p2 = new Promise(function (resolve, reject) {
  // ...
  resolve(p1);
})
复制代码

上述代码中:p1 和 p2都是Promise的实例,可是p2的 resolve方法将 p1做为参数,即一个异步操做的结果返回是另外一个异步操做。

注意:p1的状态就会传递给p2,p1的状态决定了p2的状态。若是p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;若是p1的状态已是 resolved 或者 rejected,那么p2的回调函数会当即执行。

通常来讲,调用resolve 或 reject之后,Promise的进程就就结束了,后续操做应该放到 then方法里,而不是直接写在 resolve 或 reject 的后面。另外最后在它们以前加上 return语句。

3. Promise.prototype.then()

Promise实例具备 then 方法,then方法是定义在原型对象 Promise.prototype上的。它的做用是为 Promise 实例添加状态改变时的回调函数。then 的第一个参数是 resolved状态的回调函数,第二个参数是 rejected状态的回调函数。

then方法返回的是一个新的 Promise 实例,不是原来那个,所以可使用链式写法。.then().then()

a().then((j) => {
    retrun j
}).then((i) => {
    console.log(i)
},(err)=>{
    console.log(err)
})
复制代码

上面 第一个then方法指定的回调函数,返回的是另外一个 Promise 对象。这时,第二个 then 方法指定的回调函数,就会等这个新的 Promise对象状态发生变化,若是变为 resolved,就调用第一个回调函数,若是状态变为 rejected,就调用第二个回调函数。

4. Promise.prototype.catch()

Promise.prototype.catch 方法是 .then(null, rejecton) 或 .then(undefined, rejection)的别名,用于指定发生错误时的回调函数。

a().then((p) => {
    // success
}).catch((err) => {
    console.log('err')
})
复制代码

若是对象的状态变为 resolved, 则会调用 then 方法指定的回调函数 success,若是异步操做抛出错误,状态就会变为 rejected,就会调用 catch 方法指定的回调函数处理这个错误。若是 then 方法指定的回调函数,在运行中抛出错误,也会被catch 方法捕获。

另外reject方法的做用等同于抛出错误

若是 Promise状态已经变成 resolved,再抛出错误是无效的。由于状态一旦改版,就永远保持,不会再变了。 并且Promise的错误有『冒泡』的性质,会一直向后传递,直到被捕获位置,它的错误总会被下一个catch语句捕获

建议:Promise 对象后面要跟catch方法,这样能够处理 Promise 内部发生的错误。catch方法返回的仍是一个 Promise 对象,所以后面还能够接着调用then方法。

注意: catch函数中的方法发生错误,若是后面没有别的catch 方法,那么错误将不会被捕获,若是 catch 后面 还有catch ,第二个catch将会捕获前一个catch方法抛出的错误。

5. Promise.prototype.finally()

finally 方法用于指定无论 Promise 对象最后状态如何,都会执行的操做。

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
复制代码

以上,无论promise 最后的状态,都会执行 finally 方法指定的函数。

finally 方法的回调函数不接受任何参数,因此就没法知道以前Promise状态究竟是 fulfilled 仍是 rejected。因此在finally方法里面的操做,是与以前状态无关的并且不依赖于Promise的执行结果。

6. Promise.all()

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

const p = Promise.all([p1, p2, p3])
复制代码

Promise.all 方法接受一个数组做为参数,p一、p二、p3都是Promise实例,若是不是,就会先调用Promise.resolve方法,将参数转为 Promise 实例再处理。(Promise.all 方法的参数能够不是数组,但必须具备 Iterator 接口,且返回的每一个成员都是 Promise 实例。)

Promise.all 的状态有两种状况:

一、若是 p1 p2 p3的状态都变成了 fulfilled,p的状态才是fulfilled,这时候返回一个 p1 p2 p3返回值组成的数组,传递给 p 的回调函数。

二、若是 p1 p2 p3中任一一个被rejected,p 的状态就变成了 rejected,这时候返回的是第一个被 rejected 实例的返回值,传递给 p 的回调函数。

注意,若是做为参数的 Promise 实例,本身定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。而是触发本身定义的catch方法。

7. Promise.race()

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

const p = Promise.race([p1, p2, p3]);
复制代码

与 Promise.all 的区别就是 p1 p2 p3 中一个实例改变状态,那么 p 的状态就跟着改变了,返回值为最早返回那个Promise实例的返回值。

8. Promise.resolve()

将现有对象转为 Promise 对象。

一、若是参数是一个Promise 实例
那么将不作任何修改。
复制代码
二、参数是一个 thenable对象(具备then方法的对象)
将这个对象转为Promise对象,而后当即执行 thenable对象的then方法
复制代码
三、参数不是具备then方法的对象,或根本不是对象
返回一个新的Promise对象,状态为 resolved
复制代码
四、不带任何参数
直接返回一个 resolved 状态的Promise对象
复制代码

9. Promise.reject()

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。回调函数当即执行。

关注公众号 【小夭同窗】

公众号小夭同窗
相关文章
相关标签/搜索