How to use async?

前端 未结 1 738
清酒与你
清酒与你 2021-01-28 04:25

I\'m doing a for loop to check against some values, on here is a short version. What I don\'t understand is why console.log(indirizzo[a]); is giving undefined while

相关标签:
1条回答
  • 2021-01-28 04:32

    From [Mark Meyer][1] Response:

    Your main issue is that geocoder.geocode() is asynchronous and takes a callback. You are passing a function to the callback but treating the return value as if it will return from the main function, findLatLang(), but it won't. Currently findLatLang() returns nothing.

    findLatLang() is where you should have the promise and return it from the function:

    function findLatLang(address, geocoder, mainMap) {
        return new Promise(function(resolve, reject) {
            geocoder.geocode({'location': address}, function(results, status) {
                if (status === 'OK') {
                    console.log(results);
                    resolve([results[0].geometry.location.lat(), results[0].geometry.location.lng()]);
                } else {
                    reject(new Error('Couldnt\'t find the location ' + address));
                }
        })
        })
    } 
    

    Then in the loop in getPoints() you can just collect those promises into an array and call Promise.all() on the array which will give you the values once all promises have resolved:

    function getPoints(geocoder,map) {
        let locationData = [];
        var indirizzo = [];
        for (var i = 0; i < savedRepods.length; i++) {
            for (var a = 0; a < ids.length; a++) {
                if(savedRepods[i] == ids[a]) {
                    var geocoder = new google.maps.Geocoder;
                    var latlngStr = coords[a].split(',', 2);
                    var latlng = {lat: parseFloat(latlngStr[0]), lng: parseFloat(latlngStr[1])};
                    locationData.push(findLatLang(latlng, geocoder, map))
                    console.log(indirizzo[a]);
                }
            }
        }
        return locationData // array of promises
    }
    
    var locations = getPoints(geocoder,map)
    
    Promise.all(locations)     
    .then(function(returnVals){
            // you should have return values here when
            // all promises have rsolved
              console.log(returnVals);
    })
    

    The Promise.all() method returns a single Promise that fulfills when all of the promises passed as an iterable have been fulfilled or when the iterable contains no promises or when the iterable contains promises that have been fulfilled and non-promises that have been returned.

    It's not clear where addressData is coming from - you are using it in the function, but it's not being passed in anywhere.

    View proof of concept of [Mark Meyer][1] Response:

    proof of concept fiddle

    code snippet:

    (function($) {
    
        var savedRepods = <?php echo json_encode($userPostsInternal); ?>;
        savedRepods = savedRepods.split(",");
    
        var date = [],
            coords = [],
            ids = [],
            metal = [],
            plastic = [],
            paper = [],
            glass = [],
            indirizzo = [];
    
        var array = <?php echo $contents; ?>;
    
        array.map(function(item) {
            coords.push(item.Lat + "," + item.Lng);
            ids.push(item.ID);
            date.push(item.Date);
            plastic.push(item.Plastic);
            paper.push(item.Paper);
            glass.push(item.Glass);
            metal.push(item.Metal);
        });
    
        /**
        * findLatLang
        */
        function findLatLang(location, geocoder, value) {
            /**
            * Return new Promise what resolves when
            * the geocoder is successfull
            * and push in the array of promises
            */
            return new Promise(function(resolve, reject) {
                /** Do geocoder */
                geocoder.geocode({
                    'location': location
                }, function(results, status) {
                    /**
                    * If geocoder is Ok
                    */
                    if (status === 'OK') {
                        /**
                        * When the geocoder is successfull located
                        * resolve the promise and send the response of formate address
                        */
                        resolve([results[0].formatted_address, value]);
                    } else {
                        /**
                        * Reject the promise
                        */
                        reject(new Error('Couldnt\'t find the location ' + location));
                    }
                })
            })
        }
    
        /**
        * processData
        * return an array of promises
        */
        function getPoints() {
            /**
            * Declare a variable of promises that have a geocoder
            */
            let locationData = [];
            for (var i = 0; i < savedRepods.length; i++) {
                for (var a = 0; a < ids.length; a++) {
                    if (savedRepods[i] == ids[a]) {
                        var geocoder = new google.maps.Geocoder;
                        var latlngStr = coords[a].split(',', 2);
                        var latlng = {
                            lat: parseFloat(latlngStr[0]),
                            lng: parseFloat(latlngStr[1])
                        };
    
                        /**
                        * Push geocoder in array of locationdata
                        * Send the geocoder object on function and send the map
                        */
                        locationData.push(findLatLang(latlng, geocoder, a))
                    }
                }
            }
    
            /** return array of promises */
            return locationData;
        }
    
        /**
        * Now process the response from locationData
        */
        var locations = getPoints();
    
        /**
        * Promise all
        * freecodecamp.org/news/…
        * The Promise.all() method returns a single Promise that fulfills when all of the promises
        * passed as an iterable have been fulfilled or when the iterable contains no promises or when
        * the iterable contains promises that have been fulfilled and non-promises that have been returned.
        * It rejects with the reason of the first promise that rejects, or with the error caught by the
        * first argument if that argument has caught an error inside it using try/catch/throw blocks.
        * ONLY RETURN VALUE WHEN ALL PROMISES HAS ENDED
        * @TODO => SHOW LOADER IN PROCESS
        */
    
        Promise.all(locations)
            .then(function(returnVals) {
                console.warn(returnVals)
                _indirizzo = returnVals;
                doAddress(_indirizzo)
            });
    
        function doAddress(_indirizzo) {
            _indirizzo.forEach(function(item) {
                var a = item[1];
                var location = item[0];
                $("#eachValue ul").append("<li class='list-group-item'>repod id= " + ids[a] + "<br> Indirizzo = " + location + "<br> Metallo = " + metal[a] + ", <br> Plastica = " + plastic[a] + ", <br> Vetro = " + glass[a] + ", <br> Carta = " + paper[a] + "</li>");
            })
        }
    
    })(jQuery);
    
    0 讨论(0)
提交回复
热议问题