zoukankan      html  css  js  c++  java
  • ES6 中 Promise

    在说Promise之前我们先简单说一下什么是同步异步?

       同步(Sync):所谓同步,就是发出一个功能调用时,在没有得到结果之前,该调用就不返回或继续执行后续操作。

       异步(Async):异步与同步相对,当一个异步过程调用发出后,调用者在没有得到结果之前,就可以继续执行后续操作。当这个调用完成后,一般通过状态、通知和回调来通知调用者。

    Promise是什么?

      Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一。这句话说的很明白了,Promise是一种用于解决异步问题的思路、方案或者对象方式。

      在js中,经常使用异步的地方是Ajax交互。比如在es5时代,jQueryajax的使用success来完成异步的:

    $.ajax({
       url:'/xxx',
       success:()=>{},
       error: ()=>{}
    })

      这种方法可以清楚的让读代码的人明白那一部分是Ajax请求成功的回调函数和失败的回调函数。但是问题来了,当一次请求需要连续请求多个接口时,这段代码仿佛进入了一团乱麻中:

    // 第一次 
    $.ajax({
         url:'/xxx',
         success:()=>{
             // 第二次
             $.ajax({
                 url:'/xxx',
                 success:()=>{
                   // 第三次
                   $.ajax({
                      url:'/xxx',
                      success:()=>{
                       // 可能还会有
                      },
                      error: ()=>{}
                    })
                 },
                 error: ()=>{}
            })
         },
         error: ()=>{}
    }) 

      也许因为success和error这两个函数的存在,理解这段代码会很简单,但是当我们更改需求的时候,这将成为一个棘手的问题。这就是回调地狱。

      当然,这是es5时代。当js这门语言发展到es6时代时,Promise的出现给异步带来了变革。Promise提供一个then,来为异步提供回调函数:

    $.ajax({
        url:'/xxx',
    }).then( ()=>{
       // 成功的回调
    }, ()=>{
      // 失败的回调 
    })

      而其先进之处则是,可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作。

    Promise的特点?

    • 对象的状态不会受到外界的影响。Promise代表的是一个异步的操作。一共有三种状态pending(进行中),resolved(已做完)和rejected(已失败),异步操作的结果,决定这Promise最终的状态。成功的则会使用resolved作为回调,如果失败则会使用rejected作为回调,任何的操作都无法改变其中的状态。
    • Promise的状态一旦改变,就永远不会再改变。Promise的改变只有两种情况,Pending –> rejected或者Pending-> resolved,Promise的最大特点也就是在此,如果你错过了他的返回结果,如果再想通过某种方法,去获得Promise的返回结果是获取不到的。

    简单来说,Promise 就是用同步的方式写异步的代码,用来解决回调问题

    then()方法

      then 方法就是把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。

      而 Promise 的优势就在于这个链式调用。我们可以在 then 方法中继续写 Promise 对象并返回,然后继续调用 then 来进行回调操作。

      下面做一个吃早饭的演示,它们是层层依赖的关系,下一步的的操作需要使用上一部操作的结果。(这里使用 setTimeout 模拟异步操作),正式开发可以用 ajax 异步

        function cake() {
          console.log('排队买早饭')
          let breakfast = new Promise((resolve, reject) => {
            setTimeout(() => {
              console.log('买了手抓饼')
              resolve('手抓饼')
            }, 100)
          })
          return breakfast
        }
    
        function eat(data) {
          console.log('开始吃早饭:' + data)
          let eatbreakfast = new Promise((resolve, reject) => {
            setTimeout(() => {
              console.log('吃完早饭')
              resolve('去上班')
            }, 100)
          });
          return eatbreakfast
        }
        cake().then((res) => {
          return eat(res)
        }).then((res) => {
          console.log(res)
        })
    

      打印结果:

      

    catch()方法:

      catch在链式写法中可以捕获前面then中发送的异常。

        function cake() {
          console.log('排队买早饭')
          let breakfast = new Promise((resolve, reject) => {
            setTimeout(() => {
              console.log('没买到饼')
              reject('饼买光了')
            }, 100)
          })
          return breakfast
        }
    
        function eat(data) {
          console.log('开始吃早饭:' + data)
          let eatbreakfast = new Promise((resolve, reject) => {
            setTimeout(() => {
              console.log('吃完早饭')
              resolve('去上班')
            }, 100)
          });
          return eatbreakfast
        }
        cake().then((res) => {
          return eat(res)
        }).catch((res) => {
          console.log(res)
        })

    打印结果:

      

      它的另一个作用是,当执行 resolve 的回调(也就是上面 then 中的第一个参数)时,如果抛出异常了(代码出错了),那么也不会报错卡死 js,而是会进到这个 catch 方法中。

        function cake() {
          console.log('排队买早饭')
          let breakfast = new Promise((resolve, reject) => {
            setTimeout(() => {
              console.log('买了豆浆')
              resolve('豆浆')
            }, 100)
          })
          return breakfast
        }
    
        function eat(data) {
          console.log('开始吃早饭:' + data)
          let eatbreakfast = new Promise((resolve, reject) => {
            setTimeout(() => {
              console.log('吃完早饭')
              resolve('去上班')
            }, 100)
          });
          return eatbreakfast
        }
        cake().then((res) => {
          throw new Error("买了坏的豆浆");
          return eat(res)
        }).catch((res) => {
          console.log(res)
        })

    打印结果:

      

    all()方法:

      Promise 的 all 方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。

      比如下面代码,两个个异步操作是并行执行的,等到它们都执行完后才会进到 then 里面。同时 all 会把所有异步操作的结果放进一个数组中传给 then。

        function eat() {
          console.log('排队买手抓饼')
          let breakfast = new Promise((resolve, reject) => {
            setTimeout(() => {
              console.log('刚做好的手抓饼')
              resolve('热乎的手抓饼')
            }, 100)
          })
          return breakfast
        }
    
        function drink() {
          console.log('排队买豆浆')
          let soybean = new Promise((resolve, reject) => {
            setTimeout(() => {
              console.log('刚打磨的豆浆')
              resolve('热乎的豆浆')
            }, 100)
          })
          return soybean
        }
        Promise.all([eat(), drink()]).then((results) =>{
           console.log("早饭都买好了")
           console.log(results)
        })
    

      

    打印结果:

      

    race()方法:

      race 按字面解释,就是赛跑的意思。race 的用法与 all 一样,只不过 all 是等所有异步操作都执行完毕后才执行 then 回调。而 race 的话只要有一个异步操作执行完毕,就立刻执行 then 回调。

      注意:其它没有执行完毕的异步操作仍然会继续执行,而不是停止。

      这里我们将上面样例的 all 改成 race

        function eat() {
          console.log('排队买手抓饼')
          let breakfast = new Promise((resolve, reject) => {
            setTimeout(() => {
              console.log('刚做好的手抓饼')
              resolve('热乎的手抓饼')
            }, 100)
          })
          return breakfast
        }
    
        function drink() {
          console.log('排队买豆浆')
          let soybean = new Promise((resolve, reject) => {
            setTimeout(() => {
              console.log('刚打磨的豆浆')
              resolve('热乎的豆浆')
            }, 100)
          })
          return soybean
        }
        Promise.race([eat(), drink()]).then((results) =>{
           console.log("哈哈,早饭都买好了")
           console.log(results)
        })
    

      打印结果:

      

  • 相关阅读:
    网络流
    Link-Cut-Tree题集
    动态点分治
    斜率优化DP
    【Python学习之旅】---继承的方式完成包装(授权、item系列、str&repr、format 自定义格式方法)
    【Python学习之旅】---动态导入模块
    【Python学习之旅】---封装与反射(类的相关知识,面向对象三大特性:继承-多态-封装)
    【Python学习之旅】---多态(类的相关知识,面向对象三大特性:继承-多态-封装)
    【Python学习之旅】---多态(类的相关知识)
    【Python学习之旅】---继承(类的相关知识)
  • 原文地址:https://www.cnblogs.com/Mr-Tao/p/10517048.html
Copyright © 2011-2022 走看看