22_Promise解决回调地狱

一、回调函数

  • 什么是回调函数?

  • 就是把函数 A 当作参数传递到 函数 B 中

  • 在函数 B 中以行参的方式进行调用

    function a(cb) {
      cb()
    }
    
    function b() {
      console.log('我是函数 b')
    }
    
    a(b)
    
  • 为什么需要回调函数

    • 当我们执行一个异步的行为的时候,我们需要在一个异步行为执行完毕之后做一些事情
    • 那么,我们是没有办法提前预知这个异步行为是什么时候完成的
    • 我们就只能以回调函数的形式来进行
    • 就比如我们刚刚封装过的那个 ajax 函数里面的 success
    • 我们并不知道 ajax 请求什么时候完成,所以就要以回调函数的形式来进行

二、回调地狱

  • 当一个回调函数嵌套一个回调函数的时候

  • 就会出现一个嵌套结构

  • 当嵌套的多了就会出现回调地狱的情况

  • 比如我们发送三个 ajax 请求

    • 第一个正常发送
    • 第二个请求需要第一个请求的结果中的某一个值作为参数
    • 第三个请求需要第二个请求的结果中的某一个值作为参数
    ajax({
      url: '我是第一个请求',
      success (res) {
        // 现在发送第二个请求
        ajax({
          url: '我是第二个请求'data: { a: res.a, b: res.b },
          success (res2) {
            // 进行第三个请求
            ajax({
              url: '我是第三个请求',
              data: { a: res2.a, b: res2.b },
      				success (res3) { 
                console.log(res3) 
              }
            })
          }
        })
      }
    })
    
  • 回调地狱,其实就是回调函数嵌套过多导致的

  • 当代码成为这个结构以后,已经没有维护的可能了

  • 所以我们要把代码写的更加的艺术一些

三、Promise语法

  • promise 是一个 ES6 的语法

  • 承诺的意思,是一个专门用来解决异步 回调地狱 的问题

  • 语法:

    new Promise(function (resolve, reject) {
      // resolve 表示成功的回调
      // reject 表示失败的回调
    }).then(function (res) {
      // 成功的函数
    }).catch(function (err) {
      // 失败的函数
    })
    
  • promise 就是一个语法

    • 我们的每一个异步事件,在执行的时候
    • 都会有三个状态,执行中 / 成功 / 失败
      • pending 承诺继续
      • fulilled 成功
      • rejected 失败/拒绝
  • 因为它包含了成功的回调函数

  • 所以我们就可以使用 promise 来解决多个 ajax 发送的问题

    new Promise(function (resolve, reject) {
      ajax({
        url: '第一个请求',
        success (res) {
          resolve(res)
        }
      })
    }).then(function (res) {
      // 准备发送第二个请求
      return new Promise(function (resolve, reject) {
        ajax({
          url: '第二个请求',
          data: { a: res.a, b: res.b },
          success (res) {
            resolve(res)
          }
        })
      })
    }).then(function (res) {
      ajax({
        url: '第三个请求',
        data: { a: res.a, b: res.b },
        success (res) {
          console.log(res)
        }
      })
    })
    
  • 这个时候,我们的代码已经改观了很多了

  • 基本已经可以维护了

  • 但是对于一个程序员来说,这个样子是不够的

  • 我们还需要更加的简化代码

  • 所以我们就需要用到一个 es7 的语法了

  • 叫做 async/await

四、Promise对象的常用方法

1.then

  • 通过promise对象的then方法可以同时给p1传递成功和失败的回调函数

  • 语法: p1.then(成功的回调函数[,失败的回调函数])

  • 通过then传递的时候,调用失败的函数,没有报错提示

2.catch

  • 通过promise对象的catch方法可以给p1传递失败的回调函数

  • 语法: p1.catch(失败的回调函数)

  • 通过catch传递的时候,调用失败的函数,有报错提示

3.finally

  • 通过promise对象的finally方法可以给p1传递一个函数

  • 这个函数会在在promise结束的时候执行,不管是成功还是失败

    p1.finally(options=>{
        console.log('不管成功还是失败,只要结束了,我就会执行')
        console.log(options)
    })
    

4.all

  • 语法:Promise.all([promise对象1,promise对象2,…]).then(values=>{})

  • then里面的函数会在数组的所有promise对象结束的时候调用

  • values就是所有的promise对象调用成功回调的时候传入的实参的集合

  • 如果某一个promise对象执行了reject,all就会抛出遇到的第一个错误

    Promise.all([p1,p2,p3])
        .then((values)=>{
        console.log(Date.now()-current);// 5000
        console.log(values)
    })
    

5.race

  • 语法:Promise.race([promise对象1,promise对象2,…]).then(value=>{})

  • then里面的函数会在数组的最快的那一个promise对象结束的时候调用

  • 如果最快的那个resolve,就获取resolve中的实参

  • 如果最快的那个reject,就抛出错误

    Promise.race([p1,p2,p3]).then((value)=>{
        console.log(Date.now()-current);// 3000
        console.log(value)
    })
    

五、async/awaites7解决方案

  • async/await 是一个 es7 的语法

  • 这个语法是 回调地狱的终极解决方案

  • 语法:

    async function fn() {
      const res = await promise对象
    }
    
  • 这个是一个特殊的函数方式

  • 可以 await 一个 promise 对象

  • 可以把异步代码写的看起来像同步代码

  • 只要是一个 promise 对象,那么我们就可以使用 async/await 来书写

    async function fn() {
      const res = new Promise(function (resolve, reject) {
        ajax({
          url: '第一个地址',
          success (res) {
            resolve(res)
          }
        })
      })
      
      // res 就可以得到请求的结果
      const res2 = new Promise(function (resolve, reject) {
        ajax({
          url: '第二个地址',
          data: { a: res.a, b: res.b },
          success (res) {
            resolve(res)
          }
        })
      })
      
      const res3 = new Promise(function (resolve, reject) {
        ajax({
          url: '第三个地址',
          data: { a: res2.a, b: res2.b },
          success (res) {
            resolve(res)
          }
        })
      })
      
      // res3 就是我们要的结果
      console.log(res3)
    }
    
    • 这样的异步代码写的就看起来像一个同步代码了

六、try/catch语法

let p1 = new Promise(function(resolve,reject){
    setTimeout(function(){
        let num = 10;
        if(num>5){
            resolve('成功'+num)
        }else{
            reject('这是失败信息')
        }
    })
})

// promise语法
// p1.then((data)=>{
//     console.log(data)
// },(err)=>{
//     console.log(err)
// })

// 使用try...catch语法配合await语法
// await接收的是promise对象通过resolve传入的实参
let data;
try{
    data = await p1;
}catch(err){
    console.log(err)
}
console.log(data)
console.log(123)

七、Promise封装ajax

  • Promise 的形式封装 ajax
function pGetSend(url) {
  // 利用 promise 帮我们做一个 异步的 ajax 请求
  var p1 = new Promise(function (resolve, reject) {
    // 直接发送一个 ajax 请求
    var xhr = new XMLHttpRequest()
    xhr.open('GET', url)
    xhr.onload = function () {
      resolve(xhr.responseText) // 在请求成功的时候调用一下 resolve()
    }
    xhr.send()
  })

  return p1
}
  • ajax 相关案例
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值