当前位置: 首页 > 后端技术 > Node.js

“回调地狱”——Promise优雅解法实例

时间:2023-04-03 16:28:33 Node.js

“回调地狱”什么是“回调地狱”又叫“回调金字塔”,我们平时写代码的时候,js如果异步回调是不可避免的,比如ajax不断的异步请求数据回调方法也需要对数据进行处理,不断回调...形成回调地狱,会导致我们的代码可读性变差,而且一旦出现问题,调试不好也会导致性能下降,而nodejs是单线程的事件驱动和非阻塞的I/O模型,而I/O模型是异步的,所以nodejs在处理结果的时候需要在回调函数中执行,这也形成了回调地狱。那么我们应该如何优雅地避免回调地狱呢?递归?不!递归在一些简单的场景下还是很方便的,比如快速排序,哈哈,但是在处理复杂逻辑的时候就显得有点不合适了。。jQuery1.5提供了jQuery.when()then()方法differobject具体可以看下attheapi:http://www.css88.com/jqapi-1.9/jQuery.when/es6=>Promise,Generator,andes7=>AsyncPromise是一个构造函数,用来传递异步操作消息和链式调用,避免嵌套回调函数。Promise接收两个函数参数,resolve和reject,分别表示异步操作执行成功后的回调和失败的回调。Promise在声明时已经执行。有三种状态:pendinginprogress,resolvecompleted,rejectedfailed,这些状态只能从pending->resolved,pending->rejected变化。一旦promise实例发生变化,就无法再次更改。这个结果可以随时得到。例1:用三个小球依次向右移动functionmoving(obj,left){//创建一个promise实例,传入两个函数参数设置promise的状态returnnewPromise(function(resolve,reject){varleftPos=parseInt(obj.css('margin-left'));if(leftPos!=left){vartimer=setInterval(()=>{leftPos+=2;obj.css('margin-left',leftPos);if(leftPos==left){clearInterval(timer)resolve()//成功移动完成后,返回一个resolved状态,收到后继续执行下一个回调}},10)}else{resolve()}})}//使用promise链操作方式通过传递状态调用回调函数moving($('.b1'),100).then(function(){//当b1移动完成并成功时,链调用b2returnmoving($('.b2'),200)//thenfunction返回一个新的promise对象,continuethen}).then(function(){//当b2移动完成并成功后,链上调用b3returnmoving($('.b3'),300)})例2:ajax异步调用ajax异步回调问题,我们需要优雅的避免各种回调嵌套,这里我举个例子:分别请求两个接口,等到接收到数据再进行业务处理//获取商品列表实例化promise并传入resolve和reject两个参数vargetGoodsList=newPromise(function(resolve,reject){axios.get('/ggserver/api/products/list',{params}).then(函数(res){if(res.data.code=='200'){resolve(res.data.result)//成功}else{reject(res.data.errMsg)//失败}})})//我们请求的是分类列表vargetGoodsType=newPromise(function(resolve,reject){axios.get('/ggserver/api/goodsType').then(function(res){if(res.data.code=='200'){resolve(res.data.result)//成功}else{reject(res.data.errMsg)//失败}})})然后对获取到的数据进行处理getGoodsList.then(function(goodslistdata){//处理业务}).catch(function(errMsg){//业务失败console.log('哎,goodslist运气不好...')})getGoodsType.then(function(goodsTypedata){//处理业务}).catch(function(errMsg){//失败的业务console.log('哎,goodstyoe运气不好...')})最后,我们使用promise.all()方法等待列表和类型被加载以进行其他业务处理。Promise.all([getGoodsList,getGoodsType]).then(function([data1,data2]){console.log(data1,data2,'加载完成')})