Common application scenarios of front-end Promsie

Keywords: network Javascript Google Mobile

This article will summarize the common application scenarios of Promise in our project development based on our own use of ES6 Promise. Of course, Promise may not be the only option, but as a qualified front-end developer, we need to understand it.

Promsie.all

Syntax: Promise.all (iterable)

Parameter: an iterative object, such as Array.

Return value:

  • If the iterable passed is empty, it is a resolved Promise.

    Promise.all([]).then(res=>{
        console.log(res)//[]
    })
    Copy code
  • Promise resolved asynchronously (if the iteratable passed does not contain promise). Note that in this case, Google Chrome 58 returns the resolved commitment.

    Promise.all([1,2,3]).then(res=>{
        console.log(res)//[1,2,3]
    })
    Copy code
  • When all promises in a given iteratable object are resolved, or any promises are rejected, the returned promises will be asynchronously parsed / rejected (when the stack is empty)

    • When all promise s in a given iteratable object are resolved
      let promise1 = new Promise((resolve,reject)=>{
          resolve(1)
      })
      let promise2 = new Promise((resolve,reject)=>{
          resolve(2)
      })
      
      Promise.all([promise1,promise2,3]).then(res=>{
          console.log(res)//[1,2,3]
      })
      Copy code
    • When any promise in a given iteratable object is rejected
      let promise1 = new Promise((resolve,reject)=>{
          resolve(1)
      })
      let promise2 = new Promise((resolve,reject)=>{
          reject(2)
      })
      
      Promise.all([promise1,promise2,3]).then(res=>{
          console.log(res)
      }).catch(err=>{
          console.log(err)//2
      })
      Copy code

    Description:

    This method is very useful for summarizing the results of multiple promise. In ES6, multiple Promise.all asynchronous requests can be operated in parallel:

    1. When all results are returned successfully, return success in the order of request;

    2. If there is one failure method, the failure method will be entered;

    Scenario 1: multiple request results are combined

    Specific description: a page has multiple requests. We need all the requests to return data before processing and rendering together

    Thinking: if there are concurrent requests, the loading status of each request should be set separately. If there are multiple requests, multiple loading may overlap. The content displayed on the page varies according to the speed of the data returned from the request, which is reflected in the rendering process. To improve the user experience, we can use After all the requests return data, they are rendered together. At this time, we turn off the separate loading setting of the request and summarize the request results through Promise.all. From the beginning to the end, we can only set one loading.

    //1. Get the data list
    function getBannerList(){
        return new Promise((resolve,reject)=>{
            setTimeout(function(){
                resolve('Wheel data')
            },300)
        })
    }
    
    //2. Get the shop list
    function getStoreList(){
       return new Promise((resolve,reject)=>{
            setTimeout(function(){
                resolve('Store data')
            },500)
        })
    }
    
    //3. Get the classification list
    function getCategoryList(){
       return new Promise((resolve,reject)=>{
            setTimeout(function(){
                resolve('Categorical data')
            },700)
        })
    }
    
    function initLoad(){
        // loading.show() / / loading
        Promise.all([getBannerList(),getStoreList(),getCategoryList()]).then(res=>{
            console.log(res)
            // loading.hide() / / close loading
        }).catch(err=>{
            console.log(err)
            // loading.hide() / / close loading
        })
    }
    //Data initialization    
    initLoad()
    Copy code

    Scenario 2: merge request results and handle errors

    Description: we need to handle the data rendering and error handling logic of a single request. If there are multiple requests, we need to write them in multiple places

    Thinking: can we merge multiple requests together? Even if some requests fail, they will be returned to us. We only need to process the data and wrong logic in one place.

    //1. Get the data list of the carousel
    function getBannerList(){
        return new Promise((resolve,reject)=>{
            setTimeout(function(){
                // resolve('carousel data ')
                reject('Failed to get the data of the carousel')
            },300)
        })
    }
    
    //2. Get the shop list
    function getStoreList(){
       return new Promise((resolve,reject)=>{
            setTimeout(function(){
                resolve('Store list data')
            },500)
        })
    }
    
    //3. Get the classification list
    function getCategoryList(){
        return new Promise((resolve,reject)=>{
            setTimeout(function(){
                resolve('Classification list data')
            },700)
        })
    }
    
    function initLoad(){
        // loading.show()
        Promise.all([
            getBannerList().catch(err=>err),
            getStoreList().catch(err=>err),
            getCategoryList().catch(err=>err)
        ]).then(res=>{
            console.log(res) // ["failed to get the data of carousel chart", "store data", "classification data"]
            
            if(BannerList == 'Carousel data'){
                //Rendering
            }else{
                //The logic of failed to get the data of the carousel chart
            }
            if(StoreList == 'Store list data'){
                //Rendering
            }else{
                //Logic of failed to get store list data
            }
            if(StoreList == 'Classification list data'){
                //Rendering
            }else{
                 //Logic of failed to get classification list data
            }
            
            // loading.hide()
        })
    }
    
    initLoad()
    Copy code

    Sometimes the page hangs up, maybe because of the interface exception, maybe it's just a trivial interface. So why does an interface hang up causing the whole page to have no data? Project.all tells us that if there is a reject in the project parameter and the instance callback fails, the then method callback will not be executed. The above use case can solve this problem

    Application scenario 3: verify whether multiple request results meet the conditions

    Description: in a wechat applet project, the input content security verification of a form is done by calling the method written by the cloud function. The form has seven fields that need to be verified, all of which are called content security verification interfaces. If all of them pass the verification, they can be submitted normally

    function verify1(content){
        return new Promise((resolve,reject)=>{
            setTimeout(function(){
                resolve(true)
            },200)
        })
    }
    
    function verify2(content){
        return new Promise((resolve,reject)=>{
            setTimeout(function(){
                resolve(true)
            },700)
        })
    }
    
    function verify3(content){
        return new Promise((resolve,reject)=>{
            setTimeout(function(){
                resolve(true)
            },300)
        })
    }
    
    
    
    Promise.all([verify1('Verify the contents of field 1'),verify2('Verify the contents of field 2'),verify3('Verify the contents of field 3')]).then(result=>{
        console.log(result)//[true, true, true]
    
        let verifyResult = result.every(item=>item)
        //Verification results
        console.log(verifyResult?'Through validation':'Failed validation')// Through validation
    }).catch(err=>{
        console.log(err)
    })
    Copy code

    Promsie.race

    Syntax: Promise.race (iterable)

    Parameter: an object that iterable can iterate over, such as Array. Iterative.

    Return value: the Promise.race(iterable) method returns a promise. Once a promise in the iterator is resolved or rejected, the returned promise will be resolved or rejected

    The t race function returns a promise that will be completed in the same way as the first promise passed. It can be resolutions or rejections, depending on which of the two is the first way to complete.

    If the passed iteration is empty, the returned promise will wait forever.

    If the iteration contains one or more uncommitted values and / or resolved / rejected commitments, Promise.race resolves to the first value found in the iteration.

    Application scenario 1: picture request timeout

    //Request a picture resource
    function requestImg(){
        var p = new Promise(function(resolve, reject){
            var img = new Image();
            img.onload = function(){
               resolve(img);
            }
            //img.src = "https://b-gold-cdn.xitu.io/v3/static/img/logo.a7995ad.svg"; correct
            img.src = "https://b-gold-cdn.xitu.io/v3/static/img/logo.a7995ad.svg1";
        });
        return p;
    }
    
    //Delay function for timing requests
    function timeout(){
        var p = new Promise(function(resolve, reject){
            setTimeout(function(){
                reject('Picture request timeout');
            }, 5000);
        });
        return p;
    }
    
    Promise
    .race([requestImg(), timeout()])
    .then(function(results){
        console.log(results);
    })
    .catch(function(reason){
        console.log(reason);
    });
    Copy code

    Application scenario 2: request timeout prompt

    Caption: sometimes, we brush the news one second ago, and when we enter the elevator the next, you will be prompted "bad network" on the mobile page

    //request
    function request(){
        return new Promise(function(resolve, reject){
           setTimeout(()=>{
                resolve('Request successful')
           },4000)
        })
    }
    
    //Request timeout alert
    function timeout(){
        var p = new Promise(function(resolve, reject){
            setTimeout(function(){
                reject('Poor network');
            }, 3000);
        });
        return p;
    }
    
    
    
    Promise.race([
        request(),
        timeout()
    ])
    .then(res=>{
        console.log(res)
    }).catch(err=>{
        console.log(err)//Poor network
    })
    Copy code

    Promise..prototype.then

    Scenario 1: the next request depends on the result of the previous request

    Description: similar to WeChat applet login, first you need to execute the WeChat small program login wx.login, return to code, then call the login interface written at the back end, import code, and then return to token, and then each request must carry token, that is, the next request depends on the data returned by the previous request.

    function A(){
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                resolve('B Dependent data')
            },300)
        })
    }
    function B(prams){
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                resolve(prams + 'C Dependent data')
            },500)
        })
    }
    function C(prams){
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                resolve(prams)
            },1000)
        })
    }
    
    //What we expect is to try. Since there is no reject in the requests simulated by A B C, try catch is used to catch errors
    try{
        A().then( res=>B(res) ).then( res=>C(res) ).then( res=>{
            console.log(res)//Data dependent on B data dependent on C
        })   
    } catch(e){
        
    }
    Copy code

    Application scenario 2: middleware function usage

    Description: the amount of data returned by the interface is relatively large, and it seems bloated to process in one then. Multiple render data are given to each then to perform their respective duties

    //Simulate the data returned by the backend
    
    let result = {
        bannerList:[
            {img:'Broadcast map address'}
        //...
        ],
        storeList:[
            {name:'Shop list'}
        //...
        ],
        categoryList:[
            {name:'Classification list'}
        //...
        ],
        //...
    }
    
    function getInfo(){
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                resolve(result)
            },500)
        })
    }
    
    getInfo().then(res=>{
    
        let { bannerList } = res
        //Rendering a carousel
        console.log(bannerList)
        return res
    }).then(res=>{
        
        let { storeList } = res
        //Render store list
        console.log(storeList)
        return res
    }).then(res=>{
        let { categoryList } = res
        console.log(categoryList)
        //Render classification list
        
        return res
    })
    Copy code

    reference material:

    Chinese Promise - JavaScript | MDN

    Promise - JavaScript | MDN

    Conclusion:

    If you have a better idea, please leave a message

    If there is any inaccuracy or mistake in the text, please point out

    Previous articles:

    Front end code optimization practice

    Practical tools and methods in front end development

Posted by akano on Sun, 19 Apr 2020 22:37:42 -0700