解决异步回调地狱的三种方法

1.什么是异步回调地狱?

当一个函数作为参数传入另一个函数中,并且它不会立即执行,只有当满足一定条件后该函数才可以执行,这种函数就称为回调函数。回调地狱就是在此基础上代码一层层的嵌套,使代码的可读性非常差。例如:

    //回调地狱
            setTimeout(function () {  //第一层
                console.log('111');//等3秒打印111在执行下一个回调函数
                setTimeout(function () {  //第二层
                    console.log('222');//等2秒打印222在执行下一个回调函数
                    setTimeout(function () {   //第三层
                        console.log('333');//等一秒打印333
                    }, 1000)
                }, 2000)
            }, 3000)
2.解决回调地狱的方法
2.1 生成器(es6中的语法)
  • 生成器是一个特殊的函数(在函数名前面加一个*号),用来解决异步编程的回调地狱问题,语法行为和传统函数完全不同
  • yield语句:函数代码的分隔符,把函数代码切割成几块通过next()来控制代码的一个向下的执行
  • 使用iterator 迭代器对象 说明可以使用for of来遍历 每一次调用返回的结果 是yield后面的内容
  • next执行的时候是可以传参的,参数将作为上一个yield语句整体返回结果 看例子:
  
  //生成器函数实例例子
  //需求  只有拿到用户信息之后才能拿到用户的订单信息,继而拿到用户订单的商品信息
    function one(){
    setTimeout(()=>{
     let data="用户信息" 
       iterator.next(data)
    },1000)
  };
    function two(){
    setTimeout(()=>{
        let data="订单信息"  
        iterator.next(data)
    },1000)
  };
    function three(){
    setTimeout(()=>{
         let data="商品信息" 
        iterator.next(data)
    },1000)
  };
  
  function * gen(){
  let users=  yield one();
  console.log(users)
  let orders=  yield two();
  console.log(orders)
  let goods=  yield three();
  console.log(goods)
  }
  let iterator=gen()
  iterator.next()//控制台里依次打印出用户信息  订单信息  商品信息
2.2 Promise

es6引入的异步编程的新解决方案,语法上promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果

  • new Promise()括号里的参数是一个函数类型的值。且函数有两个参数,一个resolve,一个reject 分别代表成功和失败的状态,然后函数里面封装的是一个异步的操作,我们可以在函数里调用reject或者resolve来改变状态(成功或者失败)
  • 然后就可以调用.then方法
  • then方法也有两个参数,且参数是两个函数类型,每一个函数都有一个形参,成功的形参一般叫value,失败的形参一般叫reason,当我们promise里调用了resolve代表成功了,它就会执行参数是value的这个函数,反之 如果调取失败函数 也是一样的 执行reason方法
  • then方法的返回结果是promise对象,对象状态由回调函数的执行结果决定
  • 1.如果回调函数中返回的结果是非promise对象的属性,状态为成功,返回值为对象的成功状态 所以then可以链式调用
  //按顺序读取文档
  const fs=require("fs");

  const p=new Promise((resolve,reject) => {    
          fs.readFile('./book/bookOne.md',(err,data)=>{      
          resolve(data)   
          })
        })
      p.then(value=>{    
      return new Promise((resolve,reject)=>{        
      fs.readFile("./book/bookTwo.md",(err,data)=>{           
      resolve([value,data])       
      })   
   })
  }).then(value=>{   
  return new Promise((resolve,reject)=>{        
  fs.readFile('./book/bookThree.md',(err,data)=>{      
      value.push(data);            
      resolve(value)       
      })   
    })
  })
.then(value=>{    console.log(value.join('\r\n'))})


promise中catch方法

是用来指定promise对象的一个失败的回调
我们知道then方法后面两个参数都是函数,第二个函数的参数reason就是指定失败后的回调,

   const p=new Promise((resolve,reject)=>{
   
     setTimeout(()=>{
       reject("出错啦")
     },2000)
   })
   
   p.catch(function(reason){
   console.error(reason)
   })
2.3 async await

它是es8的新特性
async和await结合可以让异步代码像同步代码一样

  • async函数的返回值是一个promise对象
  • promise对象的结果由async函数执行的返回值决定

await表达式

  • 1.await必须写在async函数中
  • 2.await右侧的表达式一般为promise对象
  • 3.await返回的是promise成功的值
  • 4.await的promise失败了,就会抛出异常,需要通过try…catch捕获处理
  • 5.返回的结果如果不是一个Promise对象(return 字符串,数字类型等,undefined等),则函数返回的结果就是一个成功的Promise对象
  • 6.如果返回的结果是一个promise对象,则成功的promise 的值就是该函数成功的值
 // 例子 依次读取文件  1.md   2.md   3.md
 const fs=require("fs")

   function first({
   return new Promise((resolve,reject)=>{
    fs.readFile("./book/1.md",(err,data)=>{
      if(err) reject(err);
      resolve(data)
    })
   })
 }
 function second({
   return new Promise((resolve,reject)=>{
    fs.readFile("./book/2.md",(err,data)=>{
      if(err) reject(err);
      resolve(data)
    })
   })
 }
 
  function three({
   return new Promise((resolve,reject)=>{
    fs.readFile("./book/3.md",(err,data)=>{
      if(err) reject(err);
      resolve(data)
    })
   })
 }
 
 async book(){
  let article=await first()
  let article2=await second()
  let article3=await three()
  console.log(article.toString())//我这里文件夹里的是汉字,所以用toString转化一下
  console.log(article2.toString())
  console.log(article3.toString())
 }
 
 book()

你更喜欢哪一种语法呢,小编最喜欢 async await 嘻嘻~

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值