“Call back to hell”: promise example of elegant solution

Time:2020-11-6

What is “callback hell”

”Callback hell “is also called” callback pyramid “. When we write code, it is inevitable for JS to call back asynchronously
For example, AJAX continues to request data asynchronously, and the callback method also needs to process the data and continue to callback… Forming a callback hell
This will make our code readability worse, problems, bad debugging will also lead to performance degradation

Nodejs is a single thread event driven and non blocking I / O model, while the I / O model is asynchronous, so nodejs needs to be executed in the callback function when processing the results, thus forming a callback hell.

So how can we gracefully avoid going back to hell

Recursion? No! Recursion is very convenient to use in some simple scenarios, such as quick sort, ha ha, but it seems a bit inappropriate when dealing with complex logic

JQuery 1.5 provides jQuery.when () then() method different object
You can take a look at the API: http://www.css88.com/jqapi-1.9/jQuery.when/

ES6 = > promise, generator and ES7 = > Async
  • Promise
    Is a constructor, used to pass asynchronous operation messages, chain calls, avoid layers of nested callback functions.
    Project receives two function parameters, resolve and reject, indicating the callback after the successful execution of the asynchronous operation and the failed callback, respectively
    Promise is executed when it is declared
    There are three states: pending in progress, resolve completed, rejected failed,
    These states can only be changed from pending to resolved, pending to rejected. Once the promise instance is changed, it cannot be changed. This result can be obtained at any time

Example 1: use three small balls to move to the right in turn

function moving(obj, left){
        //Create a promise instance and pass in two function parameters to set the state of promise
        return new Promise(function(resolve,reject){
            var leftPos = parseInt(obj.css('margin-left'));
            if(leftPos != left){
                var timer = setInterval(()=>{
                    leftPos += 2;
                    obj.css('margin-left',leftPos);
                    
                    if(leftPos == left){
                        clearInterval(timer)
                        Resolve() // a status is returned after the successful movement is completed. Resolved then continues to execute the next callback after receiving it
                    }
                },10)
            }else{
                resolve()
            }
        })
    }
    //Use promise chain operation mode to call callback function by passing state
    moving($('.b1'),100)
    . then (function() {// after B1 movement completes and succeeds, B2 is called in chain
       Return moving ($('. B2'), 200) // then function returns a new promise object. Continue then
    })
    . then (function() {// when B2 movement is completed and successful, B3 is called in chain
       return moving($('.b3'),300)
    })

Example 2: Ajax asynchronous call
For the Ajax asynchronous callback problem, we should avoid various callback nesting gracefully. Here I will give an example: request two interfaces respectively, and wait until the data is received for business processing

//Get the list of goods, instantiate promise and pass in two parameters, resolve and reject
  var getGoodsList = new Promise(function(resolve,reject){
      axios.get('/ggserver/api/products/list',{params})
        .then(function(res){
            if(res.data.code == '200'){
                resolve( res.data.result )// success
            }else{
                reject( res.data.errMsg )// failed
            }
        })
  })
//We are requesting a list of categories 
var getGoodsType = new Promise(function(resolve,reject){
      axios.get('/ggserver/api/goodsType')
      .then(function(res){
           if(res.data.code == '200'){
                resolve( res.data.result )// success
            }else{
                reject( res.data.errMsg )// failed
            }
      })
})
then. The obtained data are processed in business
getGoodsList.then(function(goodslistdata){
    //Processing business
}).catch(function(errMsg){
    //Failed business
    console.log ('Oh, good luck... ')
})  
 
getGoodsType.then(function(goodsTypedata){
    //Processing business
}).catch(function(errMsg){
    //Failed business
    console.log ('Oh, good luck... ')
})
 
Finally, we passed promise.all () method to wait for the list and type to be loaded for other business processing
Promise.all([getGoodsList, getGoodsType]).then(function([data1,data2]){
    console.log (data1, data2, 'loading finished')
})