• Promise与await 的使用


    参考:https://es6.ruanyifeng.com/#docs/promise

    常用函数

    Promise.prototype.then()
    Promise.prototype.catch()
    Promise.prototype.finally()
    Promise.all()
    Promise.race() //率先改变状态,p的状态就跟着改变
    Promise.allSettled() 
    Promise.any() 
    Promise.resolve()
    Promise.reject()
    Promise.try()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    promise是什么?

    Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。简单来说,promise的作用就是将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。

    promise的特点

    • promise异步操作有三种状态:进行中,已成功,已失败。只有异步操作才能改变这个状态。
    • promise状态一旦改变,就不会再发生变化,promise对象改变的两种可能,进行中—>已成功,进行中—>已失败

    promise的基本用法

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

    const promise = new Promise(function(resolve, reject) {
      // ...
      if (/* 满足条件 成功 反之失败 */){
        resolve(value);
      } else {
        reject(error);
      }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    实例:

    promise1(){
     new Promise(function(resolve, reject) {
        let intData = Math.floor (Math.random()*10)
        if (intData > 3){
          resolve('数据正确,大于3');
        } else {
          reject('数据错误,小于3');
        }
      }).then(res=>{
        console.log(res)
      }).catch(e=>{
        console.log(e)
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    其中接受的参数是resolvereject两个函数:
    resolve的作用:将promise对象的状态由进行中—>已完成。并将异步操作的结果作为参数传递出去
    rejected的作用:将promise对象的状态由进行中—>已失败,并将异步失败的原因作为参数传递出去。

    then的用法

    then方法可以接受两个回调函数作为参数,第一个回调函数是当promise对象状态是resolve(已完成)的时候调用,第二个回调函数(可选)是当promise对象状态是reject(已失败)的时候调用。

    function timeout(ms) {
      return new Promise((resolve, reject) => {
        setTimeout(resolve, ms, 'done');
      });
    }
    
    timeout(100).then((value) => {
      console.log(value);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    链式的then用法

    then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法

    getJSON("/post/1.json").then(function(post) {
      return getJSON(post.commentURL);
    }).then(function funcA(comments) {
      // 成功
      console.log("resolved: ", comments);
    }, function funcB(err){
      // 错误
      console.log("rejected: ", err);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

    catch方法

    promise对象中,如果异步操作抛出错误,状态就会变为rejected,就会调用catch方法指定的回调函数处理这个错误,另外,then方法指定的回调函数,如果运行中抛出错误也会被catch方法捕获。

    p.then((val) => console.log('fulfilled:', val))
     .catch((err) => console.log('rejected', err));
    
    // 等同于
    // 等同于
    p.then((val) => console.log('fulfilled:', val))
     .then(null, (err) => console.log("rejected:", err));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    promise对象的错误具有“冒泡”性质,会一直向后传,直到被捕获,也就是说,会跳过中间的then函数

    getJSON('/post/1.json').then(function(post) {
      return getJSON(post.commentURL);
    }).then(function(comments) {
      // some code
    }).catch(function(error) {
      // 处理前面三个Promise产生的错误
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    finally方法

    finally方法用于指定不管promise对象最后状态如何,都会执行的操作。

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

    服务器使用promise处理请求,然后使用finally()方法关掉服务器。

    promise.all()方法

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

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

    Promise.all方法,接受的是一个数组作为参数,其中的元素都是promise实例,如果不是,则会自动将参数转变为promie实例

    p的状态是有它的数组里面的元素决定的,分两种状态(用上面举例)

    只有p1 p2 p3的状态都变成fulfilled(已完成)的状态才会变成fulfilled(已完成),此时p1 p2 p3的返回值组成一个数组,传递给p的回调函数。

    p1 p2 p3之中,有一个被rejucted(未完成),p的状态就会变成rejected(未完成),此时第一个被reject的实例的返回值,会传递给p的回调函数。

    promise.race()方法

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

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

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

    async函数

    注意:!!await命令只能用在async函数中,用在普通函数中会报错。

    async的引入,使得异步操作变得更加方便,那async函数是什么,其实它是Generator函数的语法糖。使异步函数、回调函数在语法上看上去更像同步函数。Generator这里就不介绍了。我们直接来学习async

    async返回值是一个promise对象,因此可以使用then方法添加回调函数,当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的内容。

    async function getStockPriceByName(name) {
      const symbol = await getStockSymbol(name);
      const stockPrice = await getStockPrice(symbol);
      return stockPrice;
    }
    
    getStockPriceByName('goog').then(function (result) {
      console.log(result);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    async函数的使用形式

    //函数声明
    async function foo(){}  
    
    //函数表达式
    const foo = async function(){}//对象的方法
    let obj = {async  foo(){}};
    obj.foo().then(...)
    
    //箭头函数
    const foo =async()=>{}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    async 函数内部return语句返回的值,会成为then方法调用函数的参数。

    async  function f(){
    	return ‘hello world’;
    }
    
    f().then(v=> console.log(v))
    //"hello world"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    await 命令

    正常情况下,await命令后面跟着的是一个promise对象,如果不是会自动转化为promise对象

    async function f(){
    	return await 123;
    }
    
    f().then(v =>console.log(v))
    //123
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    !!当一个await语句后面的promise变为reject,那么整个函数都会中断执行。
    async function f() {
      await Promise.reject('出错了');
      await Promise.resolve('hello world'); // 不会执行
    }
    
    • 1
    • 2
    • 3
    • 4

    错误处理

    如果await 后面的异步操作有错,那么等同于async函数返回的promis对象被reject (上文讲promise对象的时候有提到过,冒泡性质)

    async function f() {
      await new Promise(function (resolve, reject) {
        throw new Error('出错了');
      });
    }
    
    f().then(v => console.log(v))
       .catch(e => console.log(e))
    // Error:出错了
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用try …catch代码块防止出错。

    async function f() {
      try {
        await new Promise(function (resolve, reject) {
          throw new Error('出错了');
        });
      } catch(e) {
      }
      return await('hello world');
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    多个await命令都放在try…catch结构中

    async function main() {
      try {
        const val1 = await firstStep();
        const val2 = await secondStep(val1);
        const val3 = await thirdStep(val1, val2);
    
        console.log('Final: ', val3);
      }
      catch (err) {
        console.error(err);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    相关属性

    allSettled()与all()的区别

    • all()返回一个直接包裹resolve内容的数组,allSettled()返回一个包裹着对象的数组
    • all()如果有一个Promise对象报错了,则all()无法执行,会报错你的错误,无法获得其他成功的数据。allSettled()方法是不管有没有报错,把所有的Promise实例的数据都返回回来,放入到一个对象中。如果是resolve的数据则status值为fulfilled,相反则为rejected。

    Promise.resolve() 与 Promise.reject()

    resolve 成功
    reject 失败
    
    • 1
    • 2

    Promise.try()

    排错。

  • 相关阅读:
    SSL及GMVPN握手协议详解
    JS加密/解密之那些不为人知的基础逻辑运算符
    【每日一题】2760. 最长奇偶子数组-2023.11.16
    [1179]hive的lateral view用法
    STM32为什么不能跑Linux?
    【MySQL系列】MySQL表的增删改查(基础)
    RabbitMQ-第四种交换机类型
    [JavaScript]构造函数创造对象,基本包装类型
    取消SIM卡槽,eSIM为防盗带来新转机,手机防盗终极大招
    IIS搭建本地电脑服务器:通过内网穿透技术实现公网访问的步骤指南
  • 原文地址:https://blog.csdn.net/weixin_35773751/article/details/126325566