• JavaScript Promise


    Promise 是一个 ECMAScript 6 提供的类,是异步编程的一种解决方案,目的是更加优雅地书写复杂的异步任务,比传统的解决方案——回调函数和事件——更合理和更强大。


    1.基本用法(.then .catch .finally)

    Promise 类有 .then() .catch() 和 .finally() 三个方法,这三个方法的参数都是一个函数,.then() 可以将参数中的函数添加到当前 Promise 的正常执行序列,.catch() 则是设定 Promise 的异常处理序列,.finally() 是在 Promise 执行的最后一定会执行的序列。 .then() 传入的函数会按顺序依次执行,有任何异常都会直接跳到 catch 序列。

    new Promise(function (resolve, reject) {
        var a = 0;
        var b = 1;
        if (b == 0) reject("Divide zero");
        else resolve(a / b);
    }).then(function (value) {
        console.log("a / b = " + value);
    }).catch(function (err) {
        console.log(err);
    }).finally(function () {
        console.log("End");
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    执行结果:

    a / b = 0
    End
    
    • 1
    • 2

    2.Promise.resolve()

    将现有对象转为 Promise 对象
    ①参数是一个 Promise 实例
    如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。
    ②参数是一个thenable对象
    thenable对象指的是具有then方法的对象

    let thenable = {
      then: function(resolve, reject) {
        resolve(42);
      }
    };
    
    let p1 = Promise.resolve(thenable);
    p1.then(function (value) {
      console.log(value);  // 42
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    ③参数不是具有then()方法的对象,或根本就不是对象
    如果参数是一个原始值,或者是一个不具有then()方法的对象,则Promise.resolve()方法返回一个新的 Promise 对象,状态为resolved。

    const p = Promise.resolve('Hello');
    
    p.then(function (s) {
      console.log(s)
    });
    // Hello
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ④不带有任何参数
    Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的 Promise 对象。
    所以,如果希望得到一个 Promise 对象,比较方便的方法就是直接调用Promise.resolve()方法。

    const p = Promise.resolve();
    
    p.then(function () {
      // ...
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.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)
    });
    // 出错了
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4.Promise.all()

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

    Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例.
    (1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
    (2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

    5.Promise.race()

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

    只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

    6.Promise.allSettled()

    只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更。

    const promises = [
      fetch('/api-1'),
      fetch('/api-2'),
      fetch('/api-3'),
    ];
    
    await Promise.allSettled(promises);
    removeLoadingIndicator();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    上面示例中,数组promises包含了三个请求,只有等到这三个请求都结束了(不管请求成功还是失败),removeLoadingIndicator()才会执行。

    7.Promise.any()

    只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。

    const promises = [
      fetch('/endpoint-a').then(() => 'a'),
      fetch('/endpoint-b').then(() => 'b'),
      fetch('/endpoint-c').then(() => 'c'),
    ];
    
    try {
      const first = await Promise.any(promises);
      console.log(first);
    } catch (error) {
      console.log(error);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    上面代码中,Promise.any()方法的参数数组包含三个 Promise 操作。其中只要有一个变成fulfilled,Promise.any()返回的 Promise 对象就变成fulfilled。如果所有三个操作都变成rejected,那么await命令就会抛出错误。

    8.Promise.try()

    不管函数f是否包含异步操作,都用then方法指定下一步流程,用catch方法处理f抛出的错误。

    function getUsername(userId) {
      return database.users.get({id: userId})
      .then(function(user) {
        return user.name;
      });
    }
    Promise.try(() => database.users.get({id: userId}))
      .then(...)
      .catch(...)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    Spring Cloud入门看这一篇就够了
    飞象星球落地重庆云阳86所学校,县乡4万学生迎来素质课堂
    LVGL V8.2字符串显示在Keil MDK上需要注意的事项(以小熊派为例)
    ▶《强化学习的数学原理》(2024春)_西湖大学赵世钰 Ch2 贝尔曼公式
    获得进程的内核转储core
    11.16~11.19绘制图表,导入EXCEL中数据,进行拟合
    R语言替换字符串中指定字符的子串:sub函数查找字符串中第一个匹配到的子串并替换、如果要删除指定字符串子串则将替换的子符串设置为空字符串
    单例模式的介绍和五种写法
    【Python】第一课 Python环境搭建
    搞定Python常用的数据结构
  • 原文地址:https://blog.csdn.net/weixin_42826790/article/details/125403741