异步解决方案之promise

Promise对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象。

Promise的含义

  • Promise是ES6新增的异步编程解决方案,它是一个对象,可以通过Promise构造函数来实例化 new Promise(cb)

  • Promise内部的三种状态的(pending(进行中)、fulfilled(已成功)、rejected(已失败)),Promise 对象根据状态来确定执行哪个方法。Promise 在实例化的时候状态是默认 pending 的,当异步操作是完成的(调用resolve),状态会被修改为 fulfilled,如果异步操作遇到异常(调用reject),状态会被修改为 rejected,状态转化是单向的,不可逆转,已经确定的状态(fulfilled/rejected)无法转回初始状态(pending),而且只能是从 pending 到 fulfilled 或者 rejected

基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 第一步 创建实例
const promise = new Promise((resolve, reject) => {
resolve(value) // 异步操作成功
// reject(error) // 异步操作失败
})
/* Promise 构造函数接受一个函数作为参数,该函数的两个参数也是函数,resolve函数作用是将Promise对
象的状态由pending变为resolved成功,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去,
reject函数的作用是将Promise对象的状态由pending变为rejected失败,在异步操作失败时调用,并将异步操
作的错误作为参数传递出去
*/
// 第二步 使用then方法分别指定resolved和rejected状态的回调函数
promise.then(function (res) {}, function (err) {})
/* then方法接收两个回调函数作为参数,第一个回调函数是状态为resolved时调用,第二个参数是状态变为
rejected时调用,第二个函数是可选的,这两个函数都接受promise对象传出的值作为参数 */

// promise 创建后就会立即执行
let promise = new Promise(resolve => {
console.log('Promise')
resolve()
console.log('resolve后')
})
promise.then(() => {
console.log('resolved')
})
console.log('script')
// 执行结果: Promise resolve后 script resolved
/* Promise 新建后立即执行,先输出 Promise,调用resolve()后,后面的同步代码console.log('resolve 后')会先打印,then方法指定回调函数,当前脚本所有同步任务执行完才执行
接着输出同步的 script ,最后再输出 resolved */
// 一般来说 调用resolve()或reject() promise的使命就完成了,不应该在resolve()或reject()后面继续写操作,应放在then方法里面,为避免此情况,最好加上 return语句,避免意外 return resolve()

常用方法

  • Promise.prototype.then()
    它的作用是为promise实例添加状态改变时的回调函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // then方法返回的是新的promise实例,因此可以采用链式操作
    let promise = new Promise(resolve => {
    resolve('ss')
    })
    promise.then(res => {
    console.log(res) // ss
    return Promise.resolve(res + 'hh')
    }).then(res => {
    console.log(res) // sshh
    })
    // 依次指定两个then回调函数,第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数
  • Promise.prototype.catch()
    使用 Promise 对象的 catch 方法来捕获异步操作过程中出现的任何异常。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function test () {
    return new Promise((resolve, reject) => {
    reject(new Error('es'))
    })
    }
    test().catch((e) => {
    console.log(e.message) // es
    })
    // 一般来说,不要在then方法中定义rejected状态的回调函数(即第二个参数),要使用catch来处理错误
  • Promise.prototype.finally() 无论Promise对象的最后状态是啥,都会执行的操作

    1
    2
    3
    4
    5
    6
    /* finally方法指定promise结束时,无论结果是fulfilled还是rejected,都会执行的回调函数,可以避免同样的处理语句在then和catch中都要写一次的情况 */
    this.$request.then(() => {})
    .catch(() => {})
    .finally(() => {
    this.loading = false
    })
  • Promise.resolve()

    1
    2
    3
    4
    // Promise.resolve()是Promise静态方法 Promise.resolve(value)可以认为是以下代码的语法糖。
    new Promise(function (resolve) { resolve(42) })
    // 方法 Promise.resolve(value) 的返回值也是一个 Promise 对象,所以我们可以像下面那样接着对其返回值进行 .then 调用。
    Promise.resolve(42).then(function (value) { console.log(value) })
  • Promise.reject()

    1
    2
    3
    4
    // Promise.reject()是Promise静态方法 Promise.reject(error)可以认为是以下代码的语法糖。
    new Promise(function (resolve, reject) { reject(new Error('出错了')) })
    // 这段代码的功能是调用该Promise 对象通过then指定的 onRejected 函数,并将错误(Error)对象传递给这个 onRejected 函数。
    Promise.reject(new Error('BOOM!'))
  • Promise.all(promiseArray) 用于将多个promise实例包装成一个新的promise实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    var p1 = Promise.resolve(1)
    var p2 = Promise.resolve(2)
    var p3 = Promise.resolve(3)
    var p = Promise.all([p1, p2, p3]).then(function (results) {
    console.log(results) // [1, 2, 3]
    })
    // Promise.all 接收由promise实例组成的数组作为参数,如果不是promise实例,会调用Promise.resolve()处理成promise实例再进行处理
    // p的状态由 p1, p2, p3决定,分为两种情况
    // 1. 只有p1、p2、p3的状态都变为fufilled成功,最终p的状态才会变成fulfilled成功,由p1、p2、p3返回值组成的数组传递给p的回调函数
    // 如果参数中的任何一个promise为reject的话,则整个Promise.all调用会立即终止,并返回一个reject的新的 Promise 对象。
    // 2. 只要p1、p2、p3之中有一个返回rejected失败,p的状态就变成了rejectd失败,此时返回的是第一个被reject的实例的返回值,传递给p的回调函数
    // Promise.all并不是串行的 而是并行的 例如 数组中的每个请求都有延迟则promise.all()返回是延迟时间最长的大约是3s 而不是 6s
    console.time()
    const promise1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 3000, 'pro1')
    })
    const promise2 = new Promise((resolve, reject) => {
    setTimeout(resolve, 2000, 'pro2')
    })
    const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 'pro3')
    })
    Promise.all([promise1, promise2, promise3]).then((values) => {
    console.timeEnd()
    console.log(values)
    })
    // 3001.1630859375ms
    // ["pro1", "pro2", "pro3"]
  • Promise.race(promiseArray) 用于将多个promise实例包装成一个新的promise实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    var p1 = Promise.resolve(1)
    var p2 = Promise.resolve(2)
    var p3 = Promise.resolve(3)
    Promise.race([p1, p2, p3]).then(function (value) {
    console.log(value) // 1
    })
    // Promise.race返回一个新的 Promise对象。参数 promise 数组中的任何一个 Promise 对象如果变为 resolve或者 reject 的话,该函数就会返回,并使用这个 Promis 对象的值进行 resolve 或者 reject。返回最早完成的promise对象
    console.time()
    const promise1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 3000, 'pro1')
    })
    const promise2 = new Promise((resolve, reject) => {
    setTimeout(resolve, 2000, 'pro2')
    })
    const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 'pro3')
    })
    Promise.race([promise1, promise2, promise3]).then((values) => {
    console.timeEnd()
    console.log(values)
    })
    // 1000.848876953125ms
    // pro3
  • promise的链式调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    const promise1 = new Promise((resolve, reject) => {
    resolve('pro1')
    })
    const promise2 = new Promise((resolve, reject) => {
    resolve('pro2')
    })
    const promise3 = new Promise((resolve, reject) => {
    resolve('pro3')
    })
    promise1.then((res1) => {
    console.log(res1, 'res1')
    return promise2
    }).then((res2) => {
    console.log(res2, 'res2')
    return promise3
    }).then((res3) => {
    console.log(res3, 'res3')
    })
    // pro1 res1
    // pro2 res2
    // pro3 res3
-------------本文结束感谢您的阅读-------------
0%