zoukankan      html  css  js  c++  java
  • 434 ES6 的 Promise,async,await,all,race,三个状态

    1. Promise 是 es6 提出来的一个非常重要的一个语法

    2. Promise 是一种处理异步的解决方案
      通过同步编写代码的方式,处理异步的一种解决方案

    3. 以前 : 处理异步 是怎么处理的 ? 回调

    这种回调处理异步 可以的, 简单的情况下 使用 回调处理还凑活, 但是异步请求次数多, 复杂的话, 回调地狱
    
    缺点 : 
    1. 代码不优雅 
    2. 结构不清晰  
    3. 处理起来不方便.....
    
    setTimeout( ()=> {},1000)
    
    $.ajax({
      url : '..',
      data : {},
      success : res => {
      }
    })
    

    // 顺序
    // 第一次发送请求
    $.ajax({
      url : '..',
      data : {},
      success : res => {
    
        // 第二次发送请求
        $.ajax({
          url : '..',
          data : {},
          success : res => {
    
             // 第三次发送请求
             $.ajax({
              url : '..',
              data : {},
              success : res => {
    
              }
            })
    
          }
        })
    
      }
    })
    
    1. 解决方式 : Promise
    Promise.then( res => {
             //第一次发送请求
            })
            .then(res => {
              //第二次发送请求
            })
            .then(res => {
              // 第三次发送请求
            })
    

    02-Promise的基本使用.js

     /**
      * 1. Promise是一个构造函数 
      * 2. () 参数里是一个回调函数 
      *   resolve : fn  => 异步操作成功, 调用resolve
      *   reject :  fn  => 异步操作失败, 调用 reject
      * 3. Promise里面放一个异步操作
      */
    
    
     /** 
      * 1. p 是 Promise 类型 
      * 2. axios.get() 都是promise类型
      * 3. promise的类型的实例,都可以点then
      * axios.get().then()
      * axios.post().then()
      *  p.then()
      *  XXX.then()
      */
    
    
     //  自己封装的 promise
     const p = new Promise((resolve, reject) => {
         setTimeout(() => {
             // console.log('异步操作开始了');
    
             // 如果异步操作成功 => 调用 resolve  => 走 实例对象的then => 传参数
             // resolve('成功的信息')
    
             // 如果异步操作失败 => 调用 reject  => 走 实例对象的catch => 传参数
             reject('这是一条错误信息')
         }, 0);
    
     })
    
     // 供别人调用的
     p.then(res => {
             console.log('then被调用了: ', res);
         })
         .catch(err => {
             console.log('catch 被调用了: ', err);
         })
    

    03-Promise的注意点.js

    /**
     *  自定义封装Promise
     * 1. Promise 构造函数
     * 2. () 回调函数
     *   resolve
     *   reject
     * 3. Promise里面放一个异步操作
     */
    
    const p = new Promise((resolve, reject) => {
        setTimeout(() => {
            // 成功
            resolve('这是成功消息')
    
            // 失败
            // reject()
        }, 0)
    })
    
    const p = new Promise((resolve, reject) => {
        setTimeout(() => {
            // 成功
            resolve('这是成功消息')
    
            // 失败
            // reject()
        }, 0)
    })
    
    p.then(res1 => {
        console.log('then 被调用了1:', res1) // 这是成功消息
    }).then(res2 => {
        console.log('then 被调用了2: ', res2); // undefined 【因为上一个then没有指定return返回值,默认返回就是undefined。】
    }).then(res3 => {
        console.log('then 被调用了3', res3); // undefined
        return 1111
    }).then(res4 => {
        console.log('then 被调用了4', res4); // then 被调用了4 1111
    })
    
    // 注意点1 : p .then().then().then().then() .catch()...是链式编程 每次调用返回的都是 promise类型 
    
    // 注意点2 : 
    //  第一个then, 拿到的是promise类型的p中resolve返回给我们的值,
    //  第二个then, 拿到的确实undefined, 因为 p.then() => 新的promise类型实例,resolve()是空的
    //  后面的.then() 出来的都是新的promise实例
    
    //   .catch(err => {
    //   console.log('catch 被调用了')
    // })
    
    
    // 链式编程
    // p.then().catch()
    

    04-使用Promise封装一个异步读取 文件.js

    //1. 引入 模块
    const fs = require('fs')
    
    //3. 使用 Promise 封装起来
    const p = new Promise((resolve,reject) => { 
    
      fs.readFile('./a1.txt', 'utf-8', (err, data) => { 
        if (err) {
          // 执行reject,并且用return 退出函数执行
          return reject('读取失败'); 
        }
        // console.log(data)
        resolve(data)
      })
    })
    
    p.then(res => { 
      console.log('then : ',res);
    })
      .catch(err => { 
        console.log('catch:',err);
        
      })
    
    
    //2 异步读取 文件
    // fs.readFile('./a.txt', 'utf-8', (err, data) => {
    //   if (err) {
    //     return console.log('读取失败')
    //   }
    
    //   console.log(data)
    // })
    
    

    05-使用Promise封装一个异步读取多个文件.js

    // 1. 引入 模块
    const fs = require('fs')
    
    // 2. 封装promise
    function ml_readF(filepath) {
        const p = new Promise((resolve, reject) => {
            fs.readFile(filepath, 'utf-8', (err, data) => {
                if (err) {
                    return reject('读取失败')
                }
    
                resolve(data)
            })
        })
    
        return p
    }
    
    // 3. 使用
    // ml_readF('./a.txt') 读取 a.txt 的 promise
    ml_readF('./a.txt')
        .then(res1 => {
            console.log('then :', res1)
    
            return ml_readF('./b.txt')
        })
        .then(res2 => {
            console.log('then : ', res2)
            return ml_readF('./c.txt')
        })
        .then(res3 => {
            console.log('then :', res3)
        })
    
    // p.then(res1 => {
    //   console.log('then :',res1);
    // })
    

    06-async和await.js

    套路:
    使用 promise 封装异步操作函数fn,返回promise 实例,
    使用async、await 封装操作 fn的函数。


    /**
     * async 和 await 是 es8 提出来的一个语法
     * 想`同步编写代码`的方式`处理异步`, 处理的更加彻底
     
     * async: 修饰一个内部有异步操作的函数,  格式:  async + 函数
     * await: 等待一个异步操作的结果,        格式:  await 异步操作(promise类型)
     */
    
    
    // 1. 引入 模块
    const fs = require('fs')
    
    // 2. 封装promise
    function ml_readF(filepath) {
        const p = new Promise((resolve, reject) => {
            fs.readFile(filepath, 'utf-8', (err, data) => {
                if (err) {
                    return reject('读取失败')
                }
                resolve(data)
            })
        })
    
        return p
    }
    
    //3. 需求: 先后读取 a.b.c (都是异步的)
    
    // ml_readF('./a.txt').then(res => {
    //   console.log(res);
    // })
    
    // async: 修饰一个内部有(await)异步操作的函数 【不能用箭头函数。】
    async function fn() {
        // 格式 : await + promise类型 
        // 结果 : let a = ?  a 就是以前 then(res => res的结果 )
        let a = await ml_readF('./a.txt')
        console.log(a) // aaaa
    
        let b = await ml_readF('./b.txt')
        console.log(b) // 大傻春
    
        let c = await ml_readF('./c.txt')
        console.log(c) // 小马哥
    }
    
    fn()
    

    07-async和await的注意点.js

    /**
     * async 修饰一个内部有异步操作的函数   async + 函数
     * await 等待一个异步操作的结果       let res = await 异步操作(promise类型)
     */
    
    // 1. 引入 模块
    const fs = require('fs')
    
    // 2. 封装promise
    function ml_readF(filepath) {
        const p = new Promise((resolve, reject) => {
            fs.readFile(filepath, 'utf-8', (err, data) => {
                if (err) {
                    return reject('读取失败')
                }
    
                resolve(data)
            })
        })
        return p
    }
    
    /**
     * 注意点1 : async 和 await 成对出现
     * 注意点2 : async 添加的函数,一定是await `最近`的函数
     * 注意点3 : async 和 await 如果要处理异常,配合使用 try...catch
     */
    
    async function fn1() {
        // 【读取 b、c的代码放在 try中,读取 a,就报错,终端执行,不会往下读b、c,说明 await 是同步/阻塞的。】
        try {
            // 读取 a 
            let a = await ml_readF('./a1.txt')
            console.log(a)
        } catch (error) { // 捕获 异常
            console.log('读取a失败了'); // 读取a失败了
        }
    
        // 读取 b
        let b = await ml_readF('./b.txt')
        console.log(b); // 大傻
    
        // 读取 c 
        let c = await ml_readF('./c.txt')
        console.log(c); // 小马哥 
    }
    
    fn1()
    

    08-尝试改造axios.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <script src="./node_modules/axios/dist/axios.js"></script>
        <script>
            /*  */
            /* axios
                .get(
                    'http://localhost:8888/api/private/v1/login?username=admin&password=123456'
                )
                .then(res => {
                    console.log(res)
                })
    
            let p = axios
                .get(
                    'http://localhost:8888/api/private/v1/login?username=admin&password=123456'
                )
            console.log(p); // Promise对象 */
    
    
            // 既然 axios.get() 就是一个promise类型 就可以使用 async 和 await 改造
    
            // async 修饰一个函数
            // await  等待一个结果
    
            async function fn() {
                let res = await axios.get('http://localhost:8888/api/private/v1/login?username=admin&password=123456')
                console.log(res)
            }
            fn()
        </script>
    </body>
    
    </html>
    

    09-Promise的其他两个方法的使用.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
          需求1 : 想让三个异步请求都完成了, 再执行我们的操作
          Promise.all([n个异步请求]) 
    
          需求2 : 只要其中的一个完成了,就可以执行我的操作 (竞赛)
          Promise.race() 
         -->
    
        <!-- 
             json-server的url规则:http://localhost:3000/ + key
             data.json的数据:
             {
                "one": [11, 12, 13, 14],
                "two": [21, 22, 23, 24],
                "three": [31, 32, 33, 34]
            }
          -->
    
        <script src="./node_modules/axios/dist/axios.js"></script>
        <script>
            // Promise.race([
            //     axios.get('http://localhost:3000/one'),
            //     axios.get('http://localhost:3000/two'),
            //     axios.get('http://localhost:3000/three')
            // ]).then(res => {
            //     console.log('res : ', res)
            //     console.log('开始我们的操作了')
            // })
    
            Promise.all([
                axios.get('http://localhost:3000/one'),
                axios.get('http://localhost:3000/two'),
                axios.get('http://localhost:3000/three')
            ]).then(res => {
                console.log('res : ', res)
                console.log('开始我们的操作了')
            })
        </script>
    </body>
    
    </html>
    


    10-Promise的三个状态.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <title>Document</title>
      </head>
      <body>
        <script>
          /**
           * 三个状态 :
           * pending  等待/进行中
           * resolved  操作成功
           * rejected  操作失败
           */
          const p = new Promise((resolve, reject) => {
            setTimeout(() => {
              reject()
            }, 0)
          })
    
          console.log(p)
        </script>
      </body>
    </html>
    
    

    async, await

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>async函数</title>
    </head>
    
    <body>
    
        <!--
            async函数(源自ES2017)
            概念: 真正意义上去解决异步回调的问题,同步流程表达异步操作
            本质: Generator的语法糖
    
            语法:
                async function foo(){
                    await 异步操作;
                    await 异步操作;
                }
    
            特点:
                1、不需要像Generator去调用next方法,遇到await等待,当前的异步操作完成就往下执行
                2、返回的总是Promise对象,可以用then方法进行下一步操作
                3、async取代Generator函数的星号*,await取代Generator的yield
                4、语意上更为明确,使用简单,经验证,暂时没有副作用
        -->
    
        <script type="text/javascript" src="./js/jquery-1.10.1.min.js"></script>
    
        <script type="text/javascript">
            async function timeout(ms) {
                return new Promise(resolve => {
                    setTimeout(resolve, ms);
                })
            }
    
            async function asyncPrint(value, ms) {
                console.log('函数执行', new Date().toTimeString()); // 函数执行 17:42:33
                await timeout(ms);
                console.log('延时时间', new Date().toTimeString()); // 延时时间 17:42:35
                console.log(value); // hello async
            }
    
            console.log(asyncPrint('hello async', 2000)); // Promise 
    
    
            // await 
            async function awaitTest() {
                let result = await Promise.resolve('执行成功');
                console.log(result); // 执行成功
    
                let result2 = await Promise.reject('执行失败');
                console.log(result2); // Promise {<rejected>: "执行失败"}
    
                // 执行不了 【上一步报错了】
                let result3 = await Promise.resolve('还想执行一次'); 
                console.log(result3); // 
            }
    
            awaitTest();
    
            /*  
            // 案例演示
            async function sendXml(url) {
                return new Promise((resolve, reject) => {
                    $.ajax({
                        url,
                        type: 'GET',
                        success: data => resolve(data),
                        error: error => reject(error)
                    })
                })
            }
    
            async function getNews(url) {
                let result = await sendXml(url);
                let result2 = await sendXml(url);
                console.log(result, result2);
            }
            getNews('http://localhost:3000/news?id=2')
            */
        </script>
    
    </body>
    
    </html>
    
  • 相关阅读:
    给伪类设置z-index= -1;
    UITextView的字数限制 及 添加自定义PlaceHolder
    UIView 翻转动画
    viewController的自动扩展属性导致TableViewGroupStyle时向上填充
    指针属性直接赋值 最好先retain 否则内存释放导致crash
    UIButton 点击后变灰
    IOS 设置透明度导致底层View始终可见
    UIDatePicker 时间选择器
    放大Button热区的方法哟
    数组套字典排序
  • 原文地址:https://www.cnblogs.com/jianjie/p/12632596.html
Copyright © 2011-2022 走看看