之前遇见过一个面试题:面试官问我:’有个需求,它需要你调完一个接口后拿这个接口的响应数据去请求一个新的接口,并源源不断得去请求下一个新的接口,那么请问如何解决‘,这个问题就是典型的回调地狱问题
首先,回调地狱是什么?
回调函数的层层嵌套,就叫做回调地狱。回调地狱会造成代码可复用性不强,可阅读性差,可维护性(迭代性差),扩展性差等问题。
回调地狱的原因是,当人们试图以一种从上到下的视觉方式执行JS的方式编写JS,期望第1行发生的任何事情都会在第2行的代码开始运行之前完成,而代码的实际执行则事与愿违。
回调地狱的本质:①嵌套函数存在严重的耦合,牵一发而动全身。②错误处理比较艰难,不能使用try catch 和不能直接return。
解决办法:
使用promise中的then
通过链式调用,来进行实现
但是这样的话也会带来不好的体验:
(1)then的链式调⽤也会带来额外的阅读负担,不易读
(2)Promise对象一旦新建就会立即执行,无法中途取消
(3)若不设置回调函数,Promise内部会抛出错误,不会流到外部
(4)当处于pending状态时,无法得知当前处于哪一阶段
async/await:
推荐理由:
(1)内置执行器, Generator 函数的执行必须靠执行器,所以才有了 co 函数库,而 async 函数自带执行器,也就是说,async 函数的执行,与普通函数一模一样,只要一行。
(2)语义更清晰,与* 和 yield相比,async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果
(3)适用性更广,co 函数库约定,yield 命令后面只能是 Thunk 函数或 Promise 对象,而 async 函数的 await 命令后面,可以跟 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)