• "回调地狱"——优雅解决之Promise 实例


    "回调地狱"是什么

    ”回调地狱“也叫”回调金字塔“,我们平时写代码的时候 js如果异步 回调是不可避免的
    例如 ajax不断的进行异步请求数据 回调方法里还要对数据进行处理,继续回调...形成回调地狱
    这会使得我们的代码可读性变差,出现问题 不好调试 也会导致性能下降

    而nodejs 是一种单线程的事件驱动而且是非阻塞的I/O模型,而I/O模型,是异步的,这样nodejs在处理结果的时候 就需要在回调函数中执行,这样也就形成了回调地狱。

    那我们应该如何优雅的避免回调地狱呢

    递归?No! 递归用在一些简单的场景下还是很方便的,例如快速排序,哈哈,但是在处理复杂的逻辑上,似乎有点不合适..

    jQuery 1.5提供了jQuery.when() then()方法 differ对象
    具体可以看一下api:http://www.css88.com/jqapi-1.9/jQuery.when/
    
    es6 =>Promise、Generator以及 es7 => Async
    • Promise 
      是一个构造函数,用来传递异步操作消息,链式调用,避免层层嵌套的回调函数。
      promise接收两个函数参数,resolve和reject,分别表示异步操作执行成功后的回调和失败的回调
      promise在声明的时候就已经执行了 
      有三种状态:pending进行中、resolve已完成、rejected已失败,
      这些状态只能由pending -> resolved, pending -> rejected,一旦promise实例发生改变,就不能在变了,任何时候都能得到这个结果

    例子一:用三个小球依次向右运动

     1  function moving(obj, left){
     2         //创建一个promise实例 并传入两个函数参数 来设置promise的状态
     3         return new Promise(function(resolve,reject){
     4             var leftPos = parseInt(obj.css('margin-left'));
     5             if(leftPos != left){
     6                 var timer = setInterval(()=>{
     7                     leftPos += 2;
     8                     obj.css('margin-left',leftPos);
     9                     
    10                     if(leftPos == left){
    11                         clearInterval(timer)
    12                         resolve()   //成功 运动完成之后 返回一个状态resolved then接收到后继续执行下一个回调
    13                     }
    14                 },10)
    15             }else{
    16                 resolve()
    17             }
    18         })
    19     }
    20     //采用promise链式操作的方式 通过传递状态的方式来调用回调函数
    21     moving($('.b1'),100)
    22     .then(function(){                 //当b1运动完成 并且成功之后 链式调用b2
    23        return moving($('.b2'),200)    //then函数返回的是一个新的promise对象,继续then
    24     })
    25     .then(function(){                //当b2运动完成 并且成功之后 链式调用b3
    26        return moving($('.b3'),300)
    27     })

    例子二:ajax 异步调用
    ajax异步回调问题,我们要优雅的避免各种回调嵌套,这里我将做一个例子:分别请求两个接口,等到数据都拿到 在进行业务处理

     1   //获得商品列表 实例化promise 并传入resolve 和 reject两个参数
     2   var getGoodsList = new Promise(function(resolve,reject){
     3       axios.get('/ggserver/api/products/list',{params})
     4         .then(function(res){
     5             if(res.data.code == '200'){
     6                 resolve(res.data.result)      //成功
     7             }else{
     8                 reject(res.data.errMsg)       //失败
     9             }
    10         })
    11   })
    12 //我们在请求一个分类列表 
    13 var getGoodsType = new Promise(function(resolve,reject){
    14       axios.get('/ggserver/api/goodsType')
    15       .then(function(res){
    16            if(res.data.code == '200'){
    17                 resolve(res.data.result)      //成功
    18             }else{
    19                 reject(res.data.errMsg)       //失败
    20             }
    21       })
    22 })
    23 然后。在将获得的数据进行业务处理
    24 getGoodsList.then(function(goodslistdata){
    25     //处理业务
    26 }).catch(function(errMsg){
    27     //失败业务
    28     console.log('哎,goodslist运气不佳...')
    29 })  
    30  
    31 getGoodsType.then(function(goodsTypedata){
    32     //处理业务
    33 }).catch(function(errMsg){
    34     //失败业务
    35     console.log('哎,goodstyoe运气不佳...')
    36 })
    37  
    38 最后 我们通过promise.all()方法来 等列表 和 类型加载完 进行其他业务处理
    39 Promise.all([getGoodsList, getGoodsType]).then(function([data1,data2]){
    40     console.log(data1,data2,'已经加载完成啦')
    41 }) 

    案例出处 https://segmentfault.com/a/1190000012423825微博

  • 相关阅读:
    iOS地图开发
    常用iOS第三方库以及XCode插件介绍
    SDWebImage内部实现过程
    iOS-线程之GCD---之GCD的几种常用常用的方法
    iOS-线程之GCD方式---之同步异步和串行队列并行队列之间的关系
    iOS-获取系统的相册图片
    iOS开发-使用第三方库AFNetWorking解析JSON和XML数据
    iOS_UITableView上拉加载,下拉刷新
    launchImage
    launchImage
  • 原文地址:https://www.cnblogs.com/huaifeidejiushu/p/9035220.html
Copyright © 2020-2023  润新知