本文重点:解决方式:1.promise  2. 拆解 function:将各步拆解为单个的 function  3. 通过 Generator 函数暂停执行的效果方式 4. 通过ES8的异步函数 async / await
    相关链接:promise详讲 https://www.cnblogs.com/sweeeper/p/8442613.html
开始进入Callback to Hell 
 
必须知道的相关概念:
  • 什么是回调地狱?(函数作为参数层层嵌套)
    • 异步的JavaScript程序,或者说使用了回调函数的JavaScript程序,很难地去直观顺畅地阅读,,就是函数作为参数层层嵌套。代码以此种形式展现时无疑是不利于我们阅读与维护的。
  • 什么是回调函数?(一个函数作为参数需要依赖另一个函数执行调用)
    • 回调函数是必须得依赖另一个函数执行调用,它是异步执行的,也就是需要时间等待,典型的例子就是Ajax应用,比如http请求,在不刷新浏览器的情况下,当你执行DOM事件时,比如页面上点击某链接,回车等事件操作,浏览器会悄悄向服务端发送若干http请求,携带后台可识别的参数,等待服务器响应返回数据,这个过程是异步回调的,当许多功能需要连续调用,环环相扣依赖时,它就类似下面的代码,代码全部一层一层的嵌套,看起来就很庞大,很恶心,就产生了回调地狱.
  • 如何解决回调地狱
    • 保持你的代码简短(给函数取有意义的名字,见名知意,而非匿名函数,写成一大坨)
    • 模块化(函数封装,打包,每个功能独立,可以单独的定义一个js文件Vue,react中通过import导入就是一种体现)
    • 处理每一个错误
    • 创建模块时的一些经验法则
    • 承诺/生成器/ES6等
  • Promises:编写异步代码的一种方式,它仍然以自顶向下的方式执行,并且由于鼓励使用try / catch样式错误处理而处理更多类型的错误
  • Generators:生成器让你“暂停”单个函数,而不会暂停整个程序的状态,但代码要稍微复杂一些,以使代码看起来像自上而下地执行
  • Async functions:异步函数是一个建议的ES7功能,它将以更高级别的语法进一步包装生成器和继承
 

什么是“回调地狱”?

回调地狱的原因是,当人们试图以一种从上到下的视觉方式执行JavaScript的方式编写JavaScript时。很多人犯这个错误!在C,Ruby或Python等其他语言中,期望第1行发生的任何事情都会在第2行的代码开始运行之前完成,依此类推。
总结
回调地狱最主要的就是因为功能逻辑代码嵌套的层次太多,导致可读性降低,维护困难,避免回调地狱的最重要的方面是将功能移开,保持代码简单,不嵌套并分成小模块,也就是多多进行代码封装,将你所要的属性和方法用function关键字包裹起来,而且还要给它取一个有意义的名字,例如:页面上弹框,显示,隐藏,下拉等各个功能小模块,分别用有名函数给包裹起来,少用匿名函数,以便可以重复的多次使用,这也是可以便于程序流程的理解
除了常见的一种回调函数作为异步处理,还有promises,Generators,async是处理异步处理的方式,,关于这三个我也在学习当中,理论的东西虽是概念,没有大量代码的编写,个人觉得是很难理解这些东西,但是代码就是这些语言文字实实在在的转化,骚年们,加油,加油....
 
 

方法1: Promise  链式调用的方式     ES6

 Promise是异步编程的一种解决方案, 比传统的解决方案--回调函数和事件更加强大. 没有Promise之前,解决异步都是依赖回调,但执行多个具备前后顺序的异步操作时代码就会非常乱并且出现问题难调试.
上面这只是简单的数据库查询操作,当操作多时就会回调中嵌着回调,所谓的回调地狱.
横向写代码变成了纵向,更加的直观,使用then进行下一步,代码清晰.
说一下Promise的基本用法, Promise有三种状态. 可以看下面的图片
Promise一旦新建就立刻执行, 此时的状态是Pending(进行中),它接受两个参数分别是resolve和reject.它们是两个函数.
resolve函数的作用是将Promise对象的状态从'未完成'变为'成功'(由Pending变为Resolved), 在异步操作成功时,将操作结果作为参数传递出去;
reject函数的作用是将Promise对象的状态从'未完成'变为失败(由Pending变为Rejected),在异步操作失败时调用,并将异步操作的错误作为参数传递出去.
 
Promise的用法
1.生成Promise实例
  1. 执行一系列同步操作
    3.使用resolve函数将异步操作的结果传递出去, reject函数传递异步操作的错误
    4.用then方法分别指定Resolve状态和Reject状态的函数,then方法返回一个新的Promise实例,因此可以采用链式写法
 
catch函数: 用于指定发生错误时的回调函数, 可以看成是 .then( null, reject() );当执行多个then操作时,建议用catch进行错误处理, 不用每个then函数都写一个reject的回调函数
catch回捕捉到前面执行时发生的错误.
Promise.all( 传入一个数组,每一项分别是一个Promise实例 ), 当数据里的Promise状态都变为resolve时, Promise.all状态才变为resolve
只要有一个Promise的状态变为reject, Promise.all就变为reject; 可以将数组里的Promise看成是 "与" 关系
Promise.race( 传入一个数组,每一项分别是Promise实例 ), 与Promise.all相反, race可以看到 是 "或" 关系, 只要有一个Promise状态变为resolve, Promise.all 就变为resolve
Promise.resolve(): 将现有对象转为Promise对象
(1) 参数是一个Promise实例的话,不做任何变动,返回原对象
(2) 参数是一个具有then方法的对象
Promise.resolve方法会将这个对象转为Promise对象, 然后立即执行该对象的then方法
(3) 参数不具有then方法, 或者根本不是对象. Promise.resolve方法返回一个新的Promise对象, 状态为Resolve
(4) 不带任何任何参数
Promise.resolve方法直接返回一个Resolve状态的Promise对象
Promise.reject(): 返回一个新的Promise实例,该实例状态为reject; 参数用法与Promise.resolve()方法完全一致
注意
Promise.resolve(返回的数据将成为下一个then函数中的参数)

Promise.resolve()
.then(function(){
//异步函数
}).then(function(){
//异步函数
})
方法2  拆解 function:将各步拆解为单个的 function
  定时器中的回调函数处在外层函数中的作用域内,并通过参数传入,没有产生全局变量,没有重复代码。但是 function 拆分的方式其实仅仅只是拆分代码块,时常会不利于后续维护
方法3  通过 Generator 函数暂停执行的效果方式
  通过 generator 虽然能提供较好的语法结构,但是毕竟 generator 与 yield 的语境用在这里多少还有些不太贴切
 
方法4. 通过ES8的异步函数 async / await
 
async 表示这是一个 async 函数,await 只能用在这个函数里面
await 表示在这里等待 Promise 返回结果后,再继续执行
await 后面跟着的应该是一个 Promise 对象(当然,其他返回值也没关系,只是会立即执行)
await 等待的虽然是 Promise 对象,但不必写 .then() ,可以直接得到返回值
 
 

js中的回调地狱 Callback to Hell的更多相关文章

  1. 关于js中的回调函数callback

    来源于:http://www.jianshu.com/p/6bc353e5f7a3 前言 其实我一直很困惑关于js 中的callback,困惑的原因是,学习中这块看的资料少,但是平时又经常见,偶尔复制 ...

  2. 关于 js 中的回调函数 callback

    本文写于1年前 曾经的学习文章如今拿出来分享 前言 其实我一直很困惑关于js中的callback,困惑的原因是,学习中这块看的资料少,但是平时又经常见,偶尔复制一下前人代码,功能实现了也就不再去追其原 ...

  3. 关于js中的回调函数callback,通俗易懂

    前言 其实我一直很困惑关于js 中的callback,困惑的原因是,学习中这块看的资料少,但是平时又经常见,偶尔复制一下前人代码,功能实现了也就不再去追其原由,这么着,这个callback的概念就越来 ...

  4. 理解javascript中的回调函数(callback)【转】

    在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String.Array.Number.Object类的对象一样用于内置对象的管理.因为function实 ...

  5. js中的回调函数的理解和使用方法

    js中的回调函数的理解和使用方法 一. 回调函数的作用 js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数. 二. 回调函数的解释 因为 ...

  6. iOS 如何优雅的处理“回调地狱Callback hell”(一) (上)

    前言 最近看了一些Swift关于封装异步操作过程的文章,比如RxSwift,RAC等等,因为回调地狱我自己也写过,很有感触,于是就翻出了Promise来研究学习一下.现将自己的一些收获分享一下,有错误 ...

  7. JS中的回调函数实例浅析

    本文实例讲述了JS中的回调函数.分享给大家供大家参考,具体如下: 在说回调函数之前,不妨先看一段代码,相信有点js基础的同学都能明白他的含义: ? 1 2 3 document.getElementB ...

  8. 理解JS中的回调(Callback)函数

    今天写代码时写了一个函数,想实现Nodejs查询pgSQL的数据查出来并把结果作为返回值,结果发现拿不到这个值,查了下资料才恍然大悟,这是Nodejs的最大特性--非阻塞! 查询数据操作作为比较消耗资 ...

  9. js中的回调函数 和promise解决异步操作中的回调地狱问题。

    回调函数 : 函数作为参数传递到另外一个函数中.简单数据类型和引入数据类型中的数组和对象作为参数传递大家肯定都不陌生,其实引用数据类型中的函数也是可以的. 事实上大家见到的很多,用到的也很多,比如jQ ...

随机推荐

  1. CentOS7下修改默认网卡名为eth0的两种方法

    前言 大家都知道CentOS7默认的网卡名称是和设备名称是随机的,如果要修改网卡名称以 eth 开头,有两种方式,如下: 第一种方式 这种方式适合在安装操作系统的时候进行设置, 点击 Tab,打开ke ...

  2. A - Race to 1 Again

    题目 Rimi learned a new thing about integers, which is - any positive integer greater than 1 can be di ...

  3. size_t是什么?

    在32位编译器下size_t可看做unsigned int: 在64位编译器下size_t可看做unsigned long long: sizeof返回的数据类型就为size_t. C++之size_ ...

  4. SetwindowText 之线程阻塞

    示意代码: CriticalSection g_Section; CDialog g_Dlg; // 工作线程函数UINT TreadFunc_A(PVOID para){ Sleep(10); g_ ...

  5. 转:SpringMVC常见面试题总结(超详细回答)

    原文:https://blog.csdn.net/a745233700/article/details/80963758  我略微修改了下某些地方 1.什么是Spring MVC ?简单介绍下你对sp ...

  6. Oracle12c ASMM和hugepage

    在Oracle 12c,测试发现默认并不启用AMM 特性,而是使用了ASMM.因为在X86 架构下的linux 平台中,配置hugepage时,也是需要关闭AMM,使用ASMM特性. AMM分配内存的 ...

  7. qbzt day5 上午

    动态规划 递推  递归   记忆化搜索 斐波那契数列 1.用其他已经计算好的结果计算自己的结果(递推) 2.用自己的值计算别人的值(考虑对之后的项做出的贡献) cin >> n; f[]= ...

  8. qbzt day4 上午

    图论 最短路:dijkstra   spfa   floyd 最小生成树:kruskal 连通性:bfs/dfs    tarjan(强连通分量) 其它:拓扑排序    LCA 齿轮: 图的dfs树只 ...

  9. java SimpleDateFormat setLenient用法

    参考博客:https://www.cnblogs.com/my-king/p/4276577.html SimpleDateFormat.setLenient(true) : 默认值true,不严格解 ...

  10. Linux_DNS服务器

    目录 目录 DNS DNS Server ServerSite Master DNS Server Forward Domain Reverse Resolution Slave DNS Server ...