浅谈js中的回调地狱问题

浅谈js中的回调地狱问题浅谈 js 中的回调地狱问题什么是回调地狱说起回调地狱首先想到的是异步在 js 中我们经常会大量使用异步回调 例如使用 ajax 请求我们来看下面这段代码 functiona functionb c functiond 我们发现上面代码大量使用了回调函数 将一个函数作为参数传递给另个函数 并且有许多 结尾的符号 使得代码看起来很混



浅谈js中的回调地狱问题

  • 什么是回调地狱

    • 说起回调地狱 首先想到的是异步 在js中我们经常会大量使用异步回调,例如使用ajax请求
      我们来看下面这段代码:
      function a(functionb(){ 
               c(function d(){ 
               }) }) 

      我们发现上面代码大量使用了回调函数(将一个函数作为参数传递给另个函数)并且有许多 })结尾的符号,使得代码看起来很混乱。

  • 如何解决回调地狱呢

    • 第一种使用ES6中的Promise,中文翻译过来承诺,意思是在未来某一个时间点承诺返回数据给你。
    • Promise有三种状态:pending/reslove/reject 。pending就是未决,resolve可以理解为成功,reject可以理解为拒绝。
    • 同时Promise常用的三种方法 then 表示异步成功执行后的数据状态变为reslove catch 表示异步失败后执行的数据状态变为reject all表示把多个没有关系的Promise封装成一个Promise对象使用then返回一个数组数据。
    • 下面一起来看看如何使用Promise:
      function f() { 
              let promise = new Promise((resolve, reject) => { 
              //模拟异步 setTimeout(()=>{ 
              resolve('prom') },1000) }) return promise; } 

      Promise 构造函数有两个变量 resolve 用于返回异步执行成功的函数 reject 用于返回异步执行失败的函数。配合then与catch一起使用

    • 使用then获取数据
       function f1() { 
              //返回一个Promise用于下一次调用then return f().then(data=>{ 
              // 返回的数据用于下一次then使用 return data+'ise' }) } 

      使用then方法 获取到上一步resolve返回的数据

    • 获取数据
       f1().then(data=>{ 
              console.log(data) }) console.log("hello word") 

      如果猜的不错输出应该为promise在这里插入图片描述
      输出了promise 说明上面是正确的,并且先输出 hello word 后输出promise 说明Promise是异步执行的

  • 但是如果过多的使用then 也会照成新的执行流程问题。所以我们的另一位主角登场了,那就是ES6中的Generator(生成器)
    • Generator(生成器)是一种有效利用内存的机制,一边循环一边计算生成数值的机制。通过配合Promise可以更加优雅的写异步代码
    • 下面我们来试试:
      function f1() { 
              let promise = new Promise((resolve, reject) => { 
              setTimeout(function () { 
              resolve("hello word") }) }) return promise; } 

      首先我们先用Promise分装一个异步请求模拟ajax。

    • 构建一个生成器函数
       function *f() { 
              let x = yield f1(); console.log("ni hao") } 

      构建生成器非常简单 只需要在函数方法名前面加一个 * 这个函数就是一个生成器函数,可能有人注意到函数体中有一个yield关键字(学过python应该知道),简单点说yield类似return 也是返回值的,区别在于当程序 执行到yield后会返回yield后面的表达式,并且程序暂停在这里保存当前值状态,程序只是暂停在这里并没有中止。

    • 获取生成器的值
       var it = f(); it.next().value.then(data=>{ 
              console.log(data) }) console.log(123) it.next() console.log(it.next()) 

      使用next()方法可以获取到yield第一次暂停的值返回的是{ value: 值 done: true } value表示yield返回的值,done表示是否迭代完毕。当然也可以使用netx(10)来给yield设置下次执行的值。

    • 输出结果
      在这里插入图片描述
      通过结果我们看到生成器也是异步执行。




  • 当然生成器不是最完美的,它的语法让人难以理解,所以ES7推出了async/await (异步等待),多么贴切。
    • 封装异步请求
       function f() { 
              return new Promise((resolve, reject) => { 
              setTimeout(()=>{ 
              resolve("hello word") },1000) }) } 

      上面讲过了这里不再赘述。

    • 使用异步函数
      async function a(){ 
              var data = await f(); return data; } 

      函数前面加async 表示该函数是一个异步函数 await 表示等待一个异步值的到来,

    • 获取值
      var a = a() a.then(data=>{ 
              console.log(data) }) 

      异步函数返回的是一个Promise对象,到这里是不是豁然开朗了,return返回的值通过使用then来进行获取,到这里有人会问这个不是和生成器一样吗只是把* 换成async ,yield缓存await 吗? 没错确实一样,但是生成器返回的是一个迭代器,而 异步函数返回的是一个Promise,异步函数可以以更加方便的同Promise结合使用来书写同步代码风格的异步执行。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/212076.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午8:54
下一篇 2026年3月18日 下午8:54


相关推荐

  • MP算法和OMP算法及其思想

    MP算法和OMP算法及其思想

    2021年11月28日
    41
  • 保姆级教程!手把手教你用上开源版Claude Code

    保姆级教程!手把手教你用上开源版Claude Code

    2026年3月16日
    2
  • 用户地理位置的聚类算法实现—基于DBSCAN和Kmeans的混合算法

    用户地理位置的聚类算法实现—基于DBSCAN和Kmeans的混合算法用户地理位置的聚类算法实现—基于DBSCAN和Kmeans的混合算法用户地理位置的聚类算法实现基于DBSCAN和Kmeans的混合算法聚类算法简介1基于划分的Kmeans算法2基于密度的DBSCAN算法用户地理位置信息的的聚类实现1基于Kmeans的聚类实现2基于DBSCAN的聚类实现基于DBSCAN和Kmeans的混合算法实现1.聚类算法简介聚类的目标是使同一类对象

    2022年6月18日
    29
  • Ansys 圣维南原理「建议收藏」

    Ansys 圣维南原理「建议收藏」简介圣维南原理分布于弹性体上一小块面积(或体积)内的荷载所引起的物体中的应力,在离荷载作用区稍远的地方,基本上只同荷载的合力和合力矩有关;荷载的具体分布只影响荷载作用区附近的应力分布。还有一种

    2022年8月4日
    8
  • 图的同构[通俗易懂]

    图的同构[通俗易懂]图的同构Abstract图的同构为什么要研究图的同构满足什么条件的图才是图的同构同构的图案例任意两个图形,如何判定图的同构图同构的必要条件,也就是说两个图如果同构,会存在的特征图同构的必要条件举例Abstract声明:本文只为我闲暇时候学习所做笔记,仅供我无聊时复习所用,若文中有错,误导了读者,敬请谅解!!!图的同构参见我的语雀:图论:https://www.yuque.com/jhongt…

    2022年4月19日
    84
  • SpringBoot Test及注解详解(含Mockito)

    SpringBoot Test及注解详解(含Mockito)一 版本差异 SpringBoot2 2 0 版本开始引入 JUnit5 作为单元测试默认库 在 SpringBoot2 2 0 版本之前 spring boot starter test 包含了 JUnit4 的依赖 SpringBoot2 2 0 版本之后替换成了 JunitJupiter pom xml dependency groupId org springframew boot groupId dependency

    2026年3月16日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号