Javascript - synchronizing after asynchronous calls

前端 未结 6 1622
北恋
北恋 2021-02-04 02:08

I have a Javascript object that requires 2 calls out to an external server to build its contents and do anything meaningful. The object is built such that instantiating an inst

6条回答
  •  北海茫月
    2021-02-04 02:40

    That's some good stuff Mr. Kyle.

    To put it a bit simpler, I usually use a Start and a Done function.
    -The Start function takes a list of functions that will be executed.
    -The Done function gets called by the callbacks of your functions that you passed to the start method.
    -Additionally, you can pass a function, or list of functions to the done method that will be executed when the last callback completes.

    The declarations look like this.

    var PendingRequests = 0;
    function Start(Requests) {
        PendingRequests = Requests.length;
        for (var i = 0; i < Requests.length; i++)
            Requests[i]();
    };
    //Called when async responses complete. 
    function Done(CompletedEvents) {
    PendingRequests--;
        if (PendingRequests == 0) {
            for (var i = 0; i < CompletedEvents.length; i++)
                CompletedEvents[i]();
        }
    }
    

    Here's a simple example using the google maps api.

    //Variables
    var originAddress = "*Some address/zip code here*"; //Location A
    var formattedAddress; //Formatted address of Location B
    var distance; //Distance between A and B
    var location; //Location B
    
    //This is the start function above. Passing an array of two functions defined below.
    Start(new Array(GetPlaceDetails, GetDistances));
    
    
    //This function makes a request to get detailed information on a place. 
    //Then callsback with the **GetPlaceDetailsComplete** function
    function GetPlaceDetails() {
        var request = {
            reference: location.reference //Google maps reference id
        };
        var PlacesService = new google.maps.places.PlacesService(Map);
        PlacesService.getDetails(request, GetPlaceDetailsComplete);
    }
    
    function GetPlaceDetailsComplete(place, status) {
        if (status == google.maps.places.PlacesServiceStatus.OK) {
            formattedAddress = place.formatted_address;
            Done(new Array(PrintDetails));
        }
    }
    
    
    function GetDistances() {
        distService = new google.maps.DistanceMatrixService();
        distService.getDistanceMatrix(
        {
            origins: originAddress, 
            destinations: [location.geometry.location], //Location contains lat and lng
            travelMode: google.maps.TravelMode.DRIVING,
            unitSystem: google.maps.UnitSystem.IMPERIAL,
            avoidHighways: false,
            avoidTolls: false
        }, GetDistancesComplete);
    }
    function GetDistancesComplete(results, status) {
        if (status == google.maps.DistanceMatrixStatus.OK) {
            distance = results[0].distance.text;
            Done(new Array(PrintDetails));
        }
    }
    
    function PrintDetails() {
        alert(*Whatever you feel like printing.*);
    }
    

    So in a nutshell, what we're doing here is
    -Passing an array of functions to the Start function
    -The Start function calls the functions in the array and sets the number of PendingRequests
    -In the callbacks for our pending requests, we call the Done function -The Done function takes an array of functions
    -The Done function decrements the PendingRequests counter
    -If their are no more pending requests, we call the functions passed to the Done function

    That's a simple, but practicle example of sychronizing web calls. I tried to use an example of something that's widely used, so I went with the Google maps api. I hope someone finds this useful.

提交回复
热议问题