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>

posted on 2020-04-04 17:04  冲啊!  阅读(679)  评论(0编辑  收藏  举报

导航