• 94. Promise 的基本用法?


    94. Promise 的基本用法?

    创建 Promise 对象

    Promise 对象代表一个异步操作, 有三种状态: pending(进行中)、fulfilled(已成功)和 rejected(已失败)。

    Promise 构造函数接受一个函数作为参数, 该函数的两个参数分别是 resolvereject

    const promise = new Promise(function (resolve, reject) {
        // ... some code
        // 异步操作成功
        if (flag) {
            resolve(value);
        } else {
            reject(error);
        }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    一般情况下都会使用 new Promise() 来创建 promise 对象, 但是也可以使用 promise.resolvepromise.reject 这两个方法:

    Promise.resolve

    Promise.resolve(value) 的返回值也是一个 promise 对象, 可以对返回值进行 .then 调用, 代码如下:

    Promise.resolve(11).then(function (value) {
        console.log(value); // 打印出11
    });
    
    • 1
    • 2
    • 3

    resolve(11) 代码中, 会让 promise 对象进入确定(resolve 状态), 并将参数 11 传递给后面的 then 所指定的 onFulfilled 函数。

    创建 promise 对象可以使用 new Promise 的形式创建对象, 也可以使用 Promise.resolve(value) 的形式创建 promise 对象。

    Promise.reject

    Promise.reject 也是 new Promise 的快捷形式, 也创建一个 promise 对象。代码如下:

    Promise.reject(new Error('我错了, 请原谅俺!!'));
    
    • 1

    就是下面的代码 new Promise 的简单形式:

    new Promise(function (resolve, reject) {
        reject(new Error('我错了!'));
    });
    
    • 1
    • 2
    • 3

    下面是使用 resolve 方法和 reject 方法:

    function testPromise(ready) {
        return new Promise(function (resolve, reject) {
            if (ready) {
                resolve("hello world");
            } else {
                reject("No thanks");
            }
        });
    };
    // 方法调用
    testPromise(true).then(function (msg) {
        console.log(msg);
    }, function (error) {
        console.log(error);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    上面的代码的含义是给 testPromise 方法传递一个参数, 返回一个 promise 对象, 如果为 true 的话, 那么调用 promise 对象中的 resolve() 方法, 并且把其中的参数传递给后面的 then 第一个函数内, 因此打印出 hello world, 如果为 false 的话, 会调用 promise 对象中的 reject() 方法, 则会进入 then 的第二个函数内, 会打印 No thanks

    Promise 方法

    Promise 有五个常用的方法: then()catch()all()race()finally。下面就来看一下这些方法。

    then()

    Promise 执行的内容符合成功条件时, 调用 resolve 函数, 失败就调用 reject 函数。Promise 创建完了, 那该如何调用呢?

    promise.then(function (value) {
    // success
    }, function (error) {
    // failure
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    then 方法可以接受两个回调函数作为参数。第一个回调函数是 Promise 对象的状态变为 resolved 时调用, 第二个回调函数是 Promise 对象的状态变为 rejected
    时调用。其中第二个参数可以省略。then 方法返回的是一个新的 Promise 实例(不是原来那个 Promise 实例)。因此可以采用链式写法, 即 then 方法后面再调用另一个 then 方法。

    当要写有顺序的异步事件时, 需要串行时, 可以这样写:

    let promise = new Promise((resolve, reject) => {
        ajax('first').success(function (res) {
            resolve(res);
        })
    })
    promise.then(res => {
        return new Promise((resovle, reject) => {
            ajax('second').success(function (res) {
                resolve(res)
            })
        })
    }).then(res => {
        return new Promise((resovle, reject) => {
            ajax('second').success(function (res) {
                resolve(res)
            })
        })
    }).then(res => {
    
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    那当要写的事件没有顺序或者关系时, 还如何写呢?可以使用 all 方法来解决。

    catch()

    Promise 对象除了有 then 方法, 还有一个 catch 方法, 该方法相当于 then 方法的第二个参数, 指向 reject 的回调函数。不过 catch 方法还有一个作用, 就是在执行 resolve 回调函数时, 如果出现错误, 抛出异常, 不会停止运行, 而是进入 catch 方法中。

    p.then((data) => {
        console.log('resolved', data);
    }, (err) => {
        console.log('rejected', err);
    });
    p.then((data) => {
        console.log('resolved', data);
    }).catch((err) => {
        console.log('rejected', err);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    all()

    all 方法可以完成并行任务, 它接收一个数组, 数组的每一项都是一个 promise 对象。当数组中所有的 promise 的状态都达到 resolved 的时候, all 方法的状态就会变成 resolved, 如果有一个状态变成了 rejected, 那么 all 方法的状态就会变成 rejected

    let promise1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(1);
        }, 2000)
    });
    let promise2 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2);
        }, 1000)
    });
    let promise3 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(3);
        }, 3000)
    });
    Promise.all([promise1, promise2, promise3]).then(res => {
        console.log(res);
        //结果为: [1,2,3]
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    调用 all 方法时的结果成功的时候是回调函数的参数也是一个数组, 这个数组按顺序保存着每一个 promise 对象 resolve 执行时的值。

    race()

    race 方法和 all 一样, 接受的参数是一个每项都是 promise 的数组, 但是与 all 不同的是, 当最先执行完的事件执行完之后, 就直接返回该 promise对象的值。如果第一个 promise 对象状态变成 resolved, 那自身的状态变成了 resolved;反之第一个 promise 变成 rejected, 那自身状态就会变成 rejected

    let promise1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(1);
        }, 2000)
    });
    let promise2 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2);
        }, 1000)
    });
    let promise3 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(3);
        }, 3000)
    });
    Promise.race([promise1, promise2, promise3]).then(res => {
        console.log(res);
        //结果: 2
    }, rej => {
        console.log(rej)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    那么 race 方法有什么实际作用呢?当要做一件事, 超过多长时间就不做了, 可以用这个方法来解决:

    Promise.race([promise1, timeOutPromise(5000)]).then(res => {})
    
    • 1

    finally()

    finally 方法用于指定不管 Promise 对象最后状态如何, 都会执行的操作。该方法是 ES2018 引入标准的。

    promise
        .then(result => {
            // ···
        })
        .catch(error => {
            // ···
        })
        .finally(() => {
            // ···
        });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    上面代码中, 不管 promise 最后的状态, 在执行完 thencatch 指定的回调函数以后, 都会执行 finally 方法指定的回调函数。
    下面是一个例子, 服务器使用 Promise 处理请求, 然后使用 finally 方法关掉服务器。

       server.listen(port)
        .then(function () {
            // ...
        })
        .finally(server.stop);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    finally 方法的回调函数不接受任何参数, 这意味着没有办法知道, 前面的 Promise 状态到底是 fulfilled 还是 rejected。这表明, finally 方法里面的操作, 应该是与状态无关的, 不依赖于 Promise 的执行结果。finally 本质上是 then 方法的特例:

    promise.finally(() => {
        // 语句
    });
    // 等同于
    promise.then(
        result => {
            // 语句
            return result;
        },
        error => {
            // 语句
            throw error;
        }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    上面代码中, 如果不使用 finally 方法, 同样的语句需要为成功和失败两种情况各写一次。有了 finally 方法, 则只需要写一次。

  • 相关阅读:
    HUAWEI华为笔记本MateBook X 2021款i5集显(EULD-WFH9,WXX9)原装出厂Windows11系统工厂模式包
    【亲测可用】SpringBoot使用Redis的Lettuce连接池报RedisCommandTimeoutException
    vue2入门--->非单文件组件(html直接使用组件)
    媒体基础:打开多模态大模型的新思路
    深度、广度优先遍历(邻接表)
    【云原生|Docker系列7】Docker Machine 使用详解
    【MySQL】一文带你了解MySQL的基础知识
    汽车屏类产品(五):中控IVI车载信息娱乐系统
    QVHZO-A-06/18、QVHZE-A-06/36比例流量控制阀放大器
    Markdown编辑语法
  • 原文地址:https://blog.csdn.net/m0_51180924/article/details/126866621