Entiendo la noción de Promesas, pero algo parece no estar completamente claro para mí.
Tengo el siguiente html:
<!DOCTYPE html> ....... <div id="map"></div> <script src="https://maps.googleapis.com/maps/api/js?key=GOOGLE_API&callback=initialize" async></script> </body> </html> <script src="js/currentRoute.js"></script>Tengo el siguiente código JS:
async function getCurrentUserCoordinates() { console.log("Am getCurrentUserCoordinates") const url = baseUrl + `/SOME_REST_API_URL`; if (checkAdminOrTechRights(parseToken(getToken()))) { await fetch(url, { method: 'GET', headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${getToken()}` }, }) .then((response) => response .json() ) .then(terminals => { let locations = []; terminals.forEach(terminal => { locations.push({ lat: terminal.latitude, lng: terminal.longitude, name: terminal.name, location: terminal.location }) }) console.log(locations) // ALL IS PRINTING OK HERE return locations; }).catch((err) => { console.error(err); }) } } function initMap(locations) { console.log("Am initMap") console.log("printing locations: " + locations) // I HAVE UNDEFINED HERE const map = new google.maps.Map(document.getElementById("map"), { zoom: 12, center: {lat: 0.123123123123, lng: 0.123123123123}, }); const infoWindow = new google.maps.InfoWindow({ content: "", disableAutoPan: true, }); const markers = locations.map((terminal, i) => { const label = `${terminal.name}, ${terminal.location}`; const marker = new google.maps.Marker({ position: terminal, label, }); marker.addListener("click", () => { infoWindow.setContent(label); infoWindow.open(map, marker); }); return marker; }); new markerClusterer.MarkerClusterer({markers, map}); } async function initialize() { console.log("Am initialize") getCurrentUserCoordinates() .then(locations => initMap(locations)) .then(() => console.log("Am done")) .catch((err) => { console.error("ERROR!!! " + err); }) }Tengo los siguientes registros:
Am initialize currentRoute.js:2 Am getCurrentUserCoordinates currentRoute.js:28 (26) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]0: {lat: 1.123123123, lng: 1.123123123, name: 'TERM-0001', location: 'LOCATION'}1: {lat: 1.123123123, lng: 1.123123123, name: 'TERM-0099', location: 'LOCATION'}2: ............ 25: {lat: 1.123123123, lng: 1.123123123, name: 'TERM-0023', location: 'LOCATION'}length: 26[[Prototype]]: Array(0) currentRoute.js:37 Am initMap currentRoute.js:38 printing locations: undefinedEntonces, en mi opinión, se debe llamar a initMap() cuando getCurrentUserCoordinates() devuelve el resultado (ubicaciones). Dentro de las funciones, obtengo ubicaciones y, como se ve en los registros, se imprimen. Pero las ubicaciones se pasan como indefinidas dentro de las funciones initMap.
¿Qué no estoy consiguiendo aquí?
Gracias.
El principal problema con su código era que estaba llamando a return desde dentro de una función anidada dentro de la cual supuso que regresaría desde el método getCurrentUserCoordinates then pero ese no es el caso.
Su funcionalidad se puede simplificar enormemente al no mezclar async/await con then ; el primero es más fácil de administrar. El código también se beneficia al reemplazar la matriz torpe + forEach con un map simple sobre la matriz.
async function getCurrentUserCoordinates() { console.log("Am getCurrentUserCoordinates") const url = baseUrl + `/SOME_REST_API_URL`; if (checkAdminOrTechRights(parseToken(getToken()))) { try{ const result = await fetch(url, { method: 'GET', headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${getToken()}` }, }); const terminals = await result.json(); let locations = terminals.map( terminal => ({ lat: terminal.latitude, lng: terminal.longitude, name: terminal.name, location: terminal.location })) console.log(locations) // ALL IS PRINTING OK HERE return locations; } catch(err){ console.error(err); } } } * Tenga en cuenta que las return locations en este código ahora se encuentran en el ámbito externo del método en sí, sin embargo, como el método es async , en realidad devuelve una Promise , por lo que debe esperarla más adelante (ver más abajo). H/T @JeremyThille
Lo mismo es cierto más adelante en su código
async function initialize() { console.log("Am initialize") try{ const currentUserCoords = await getCurrentUserCoordinates(); const locations = initMap(currentUserCoords); console.log("Am done")) } catch(err){ console.error("ERROR!!! " + err); } }