Retrieving and using multiple JSON data from MapBox Geocoding API - JavaScript console reads "undefined is not an object"

Viewed 17

I have a JS script that gives an error when I try to use JSON data from the MapBox Geocoding API on two cities (city, state), in creating a new geojson FeatureCollection with the two places (cities) represented by markers. The markers work when I put raw coordinates in the geojson FeatureCollection geometries, but when I try to use the data from the API, I get "undefined is not an object" - even though I know the object is there, where I logged it in the console. What am I doing wrong?

<div id='map' style='width: 300px; height: 200px;'></div>
    <script>
      mapboxgl.accessToken = 'MY_ACCESS_TOKEN';
      var map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/streets-v11',
        center: [-96, 37.8],
        zoom: 3
      });

      var userData = {};

      function saveUserData(input) {
          userData = input;
          console.log(userData);
      }

      var partnerData = {};

      function savePartnerData(input) {
          partnerData = input;
          console.log(partnerData);
      }

      fetch('https://api.mapbox.com/geocoding/v5/mapbox.places/<%= @user.location.strip %>.json?limit=1&access_token=MY_ACCESS_TOKEN')
      .then(res => res.json())
      .then(data => saveUserData(data));

      fetch('https://api.mapbox.com/geocoding/v5/mapbox.places/<%= prayer_partner.location.strip %>.json?limit=1&access_token=MY_ACCESS_TOKEN')
      .then(res => res.json())
      .then(data => savePartnerData(data));

      const geojson = {
        type: 'FeatureCollection',
        features: [
          {
            type: 'Feature',
            geometry: {
              type: 'Point',
              coordinates: userData.features[0].geometry.coordinates
            },
            properties: {
              title: '<%= @user.name %>',
              description: '<%= @user.location %>'
            }
          },
          {
            type: 'Feature',
            geometry: {
              type: 'Point',
              coordinates: partnerData.features[0].geometry.coordinates
            },
            properties: {
              title: '<%= prayer_partner.name %>',
              description: '<%= prayer_partner.location %>'
            }
          }
        ]
      };

      // add markers to map
      for (const feature of geojson.features) {
        // create a HTML element for each feature
        const el = document.createElement('div');
        el.className = 'marker';

        // make a marker for each feature and add to the map
        new mapboxgl.Marker(el).setLngLat(feature.geometry.coordinates)
        .setPopup(
          new mapboxgl.Popup({ offset: 25 }) // add popups
            .setHTML(
              `<h3>${feature.properties.title}</h3><p>${feature.properties.description}</p>`
            )
        ).addTo(map);
      }

    </script>

and my JavaScript console reads:

[Error] TypeError: undefined is not an object (evaluating 'userData.features[0]')
    Global Code (1:175)
[Log] {type: "FeatureCollection", query: ["madison", "wi"], features: Array, attribution: "NOTICE: © 2022 Mapbox and its suppliers. All right…y not be retained. POI(s) provided by Foursquare."} (1, line 150)
[Log] {type: "FeatureCollection", query: ["minot", "nd"], features: Array, attribution: "NOTICE: © 2022 Mapbox and its suppliers. All right…y not be retained. POI(s) provided by Foursquare."} (1, line 157)
1 Answers

you are trying to read userData.features[0] before userData initialize. make function data => saveUserData(data) async or write code below in .then(). Read more about async in javascript

Also dont use var, use let instead. var is deprecated

Related