Vue 03 下

Vue 03

异步的结果是否可以使用返回值获取?不可以(返回结果的时机不确定)
那么必须使用回调函数的方式获取异步的结果
如果要保证异步任务的顺序,需要进行回调函数的嵌套
但是嵌套过多会出现地狱回调问题(代码可读性差)
所以诞生了新的技术解决上述问题:Promise
但是Promise也不是最好的方案,所以诞生了Async函数(最终解决方案)

异步编程-promise

promise是一种技术,用于解决回调地狱问题

promise基本用法

// 基于Promise发送请求
const p = new Promise(function (resolve, reject) {
  // 这里用于处理异步的任务
  const xhr = new XMLHttpRequest()
  xhr.open('get', 'http://localhost:3000/data')
  xhr.send(null)
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if (xhr.status === 200) {
        // 获取正常的数据
        let ret = xhr.responseText
        let obj = JSON.parse(ret)
        // 正常的结果传递给resolve即可
        resolve(obj)
      } else {
        // 返回的数据是异常的
        // 异常的结果需要传递给reject
        reject('服务器返回的数据错误')
      }
    }
  }
})

// 通过p.then方法获取异步的结果
p.then(function (ret) {
  // 这里可以得到正常的结果
  console.log(ret)
}).catch(function (err) {
  // 这里可以得到异常的结果
  console.log(err)
})

总结:
1.熟悉基于Promise处理异步任务的基本流程
2.正常的结果传递给resolve;异常的结果传递给reject
3.通过p.then获取正常的结果,p.catch获取异常的结果

解决回调地狱的问题

function queryData1() {
      // 基于Promise发送请求
      return new Promise(function (resolve, reject) {
        // 这里用于处理异步的任务
        const xhr = new XMLHttpRequest()
        xhr.open('get', 'http://localhost:3000/data1')
        xhr.send(null)
        xhr.onreadystatechange = function () {
          if (xhr.readyState === 4) {
            if (xhr.status === 200) {
              // 获取正常的数据
              let ret = xhr.responseText
              let obj = JSON.parse(ret)
              // 正常的结果传递给resolve即可
              resolve(obj)
            } else {
              // 返回的数据是异常的
              // 异常的结果需要传递给reject
              reject('服务器返回的数据错误')
            }
          }
        }
      })
    }
    function queryData2() {
      // 基于Promise发送请求
      return new Promise(function (resolve, reject) {
        // 这里用于处理异步的任务
        const xhr = new XMLHttpRequest()
        xhr.open('get', 'http://localhost:3000/data2')
        xhr.send(null)
        xhr.onreadystatechange = function () {
          if (xhr.readyState === 4) {
            if (xhr.status === 200) {
              // 获取正常的数据
              let ret = xhr.responseText
              let obj = JSON.parse(ret)
              // 正常的结果传递给resolve即可
              resolve(obj)
            } else {
              // 返回的数据是异常的
              // 异常的结果需要传递给reject
              reject('服务器返回的数据错误')
            }
          }
        }
      })
    }
    function queryData3() {
      // 基于Promise发送请求
      return new Promise(function (resolve, reject) {
        // 这里用于处理异步的任务
        const xhr = new XMLHttpRequest()
        xhr.open('get', 'http://localhost:3000/data3')
        xhr.send(null)
        xhr.onreadystatechange = function () {
          if (xhr.readyState === 4) {
            if (xhr.status === 200) {
              // 获取正常的数据
              let ret = xhr.responseText
              let obj = JSON.parse(ret)
              // 正常的结果传递给resolve即可
              resolve(obj)
            } else {
              // 返回的数据是异常的
              // 异常的结果需要传递给reject
              reject('服务器返回的数据错误')
            }
          }
        }
      })
    }

    // 如下代码执行的流程是串行的
    queryData1()
      .then(function (ret) {
        console.log(ret)
        return queryData2()
      })
      .then(function (ret) {
        console.log(ret)
        return queryData3()
      })
      .then(function (ret) {
        console.log(ret)
      })
关于promise的异常处理
// 如下代码执行的流程是串行的
queryData1()
  .then(function (ret) {
    console.log(ret)
    // 如果then中出现了异常情况,那么后续的then就不再执行了
    const arr = null
    arr.push(123)
    return queryData2()
  })
  .then(function (ret) {
    console.log(ret)
    return queryData3()
  })
  .then(function (ret) {
    console.log(ret)
  })
  .catch(function (err) {
    // 这里用于处理异常信息
    console.log(err)
  })

总结:
1.如果then中出现了异常情况,那么后续的then就不在执行了
2.一般会在then的最后添加一个catch,统一异常处理

then的回调返回值问题

// 如下代码执行的流程是串行的
queryData1()
  .then(function (ret) {
    console.log(ret)
    // 如果then中出现了异常情况,那么后续的then就不再执行了
    // const arr = null
    // arr.push(123)
    return queryData2()
  })
  .then(function (ret) {
    console.log(ret)
    // 1、这里return的值是谁?Promise的实例对象
    // 如果这里return的是Promise的实例对象,那么
    // 下一个then会得到这个Promise的异步结果
    // 其实就是这个Promise对象调用了下一个then
    return queryData3()
  })
  .then(function (ret) {
    console.log(ret)
    // 2、如果这里没有返回值,那么会默认生成一个Promise对象并返回
    // return new Promise(function (resolve) {
    //   resolve()
    // })
  })
  .then(function (ret) {
    console.log(ret)
    console.log('---------------------')
    // 3、如果这里返回的是普通数据,那么下一个then可以直接得到该数据
    // 如果返回的是普通数据,会自动包装为Promise实例对象
    return 'hello'
    // return new Promise(function (resolve) {
    //   resolve('hello')
    // })
  })
  .then(function (ret) {
    console.log(ret)
  })
  .catch(function (err) {
    // 这里用于处理异常信息
    console.log(err)
  })

总结:
1.then回调函数返回promise对象,下一个then得到这个promise任务的结果
2.then回调函数返回普通数据,下一个then可以直接得到这个数据(数据被默认包装成了promise对象)
3.then回调函数没有返回,但是可以继续then链式操作(默认返回了一个promise实例对象,但是没有值)

异步编程-Async函数

Async函数基本用法

// Asyn函数基本使用
function queryData() {
  // 基于Promise发送请求
  return new Promise(function (resolve, reject) {
    // 这里用于处理异步的任务
    const xhr = new XMLHttpRequest()
    xhr.open('get', 'http://localhost:3000/data')
    xhr.send(null)
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          // 获取正常的数据
          let ret = xhr.responseText
          let obj = JSON.parse(ret)
          // 正常的结果传递给resolve即可
          resolve(obj)
        } else {
          // 返回的数据是异常的
          // 异常的结果需要传递给reject
          reject('服务器返回的数据错误')
        }
      }
    }
  })
}

// queryData().then(function (ret) {
//   console.log(ret)
// })


// 如下就是定义了一个async函数,可以处理异步任务
async function getInfo() {
  // await关键自必须在async函数中使用
  // await之后一般跟Promise实例对象
  // const ret = await queryData()
  // console.log(ret)
  // 通过Promise的then方式获取结果和await获取结果等效
  queryData().then(function (ret) {
    console.log(ret)
  })
}
getInfo()

总结:

  1. 定义async函数仅仅需要在函数声明的左侧添加async关键字
  2. await关键字必须出现在async函数内部
  3. await关键字之后一般会跟Promise实例对象
  4. await代码行之后的代码是阻塞的

Async处理多个异步任务

// 要求:获取的顺序 jerry -> spike -> tom
async function getResult() {
  const ret2 = await queryData2()
  const ret3 = await queryData3()
  const ret1 = await queryData1()
  console.log(ret2)
  console.log(ret3)
  console.log(ret1)
}
getResult()

总结:

  1. 基于Async函数处理回调地狱可以按照同步的风格写代码,体验很好
  2. 多个await运行模式是串行的

Async函数和promise的关系

// Promise和Async函数的关系
// 1、await之后一把跟Promise实例对象,await左侧接收的值就是Promise异步任务的结果
// 2、async函数的返回值是Promise对象,而不是具体数据
function queryData() {
  // 基于Promise发送请求
  return new Promise(function (resolve, reject) {
    // 这里用于处理异步的任务
    const xhr = new XMLHttpRequest()
    xhr.open('get', 'http://localhost:3000/data')
    xhr.send(null)
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          // 获取正常的数据
          let ret = xhr.responseText
          let obj = JSON.parse(ret)
          // 正常的结果传递给resolve即可
          resolve(obj)
        } else {
          // 返回的数据是异常的
          // 异常的结果需要传递给reject
          reject('服务器返回的数据错误')
        }
      }
    }
  })
}

async function getInfo() {
  const ret = await queryData()
  // console.log(ret)
  return ret
  // 这里返回的数据实际上会默认包装为Promise实例对象
  // return new Promise(function (resolve) {
  //   resolve(ret)
  // })
}
// async函数的返回值是Promise对象,而不是具体数据
const t = getInfo()
// console.log(t)
t.then(function (ret) {
  console.log(ret)
})

总结:

  1. await之后一把跟Promise实例对象,await左侧接收的值就是Promise异步任务的结果
  2. async函数的返回值是Promise对象,而不是具体数据

axios调用接口

<body>
  <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
  <script>
    // axios调用接口
    // axios.get('http://localhost:3000/data').then(function (ret) {
    //   console.log(ret.data)
    // })

    axios.defaults.baseURL = 'http://localhost:3000/'
    async function getResult() {
      const ret = await axios.get('data')
      console.log(ret.data)
    }
    getResult()

    // 如下的伪代码
    new Vue({
      el: '#app',
      data: {
        list: []
      },
      methods: {
        // loadBookList: async function () {
        //  const ret = await axios.get('data')
        //  this.list = ret.data
        // },
        async loadBookList() {
          const ret = await axios.get('data')
          this.list = ret.data
        }
      }
    })
  </script>
</body>

总结:

  1. axios库底层封装了Promise,所有他的API一般都支持Promise方式
  2. 基于async函数处理axios的接口调用会变得异常简单
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值