0

I am making API request to local bus transit. I am getting the JSON object, which I needed. But when I am trying to access the stop key inside that object. it says cannot read the property of undefined. But when I check the object it is there to read.

error is in addDataToHtml . I am new to JS please let me know what mistake I am making here.

const apiKey = 'XXXXXXXXXXXXXX';
const query = 'streets.json?name=henlow bay&';
const stops = 'stops.json?street='
let stopsArray;
let promises = [];
const mainDiv = document.querySelector('.main-container')

const stopSchedules = stopKey => {
  return fetch(`${host}stops/${stopKey}/schedule.json?${apiKey}`)
}

const promise = json => {
  json.stops.forEach(e => {
    promises.push(stopSchedules(e.key))
  })
  return promises;
}

const addDataToHtml = jsonData => {
  Promise.all(promise(jsonData))
    .then(response => {
      return stopsArray = response.map( e => e.json())
    })
    .then((response)=> {
      console.log(response);
       response.forEach(e =>{
       console.log(e['stop-schedule'].stop.name);
       })
    })  
}

fetch(`${host}${query}${apiKey}`)
  .then((response) => response.json())
  .then((responseData) => fetch(`${host}${stops}${responseData.streets[0].key}&${apiKey}`))
  .then((stopsRespose) => stopsRespose.json())
  .then((stopsJson) => addDataToHtml(stopsJson))

And the Json object I am getting here is below.

{
  "stop-schedule": {
    "stop": {
      "key": 60433,
      "name": "Northbound Henlow at Fultz",
      "number": 60433,
      "direction": "Northbound",
      "side": "Farside",
      "street": {
        "key": 1717,
        "name": "Henlow Bay",
        "type": "Bay"
      },
      "cross-street": {
        "key": 1400,
        "name": "Fultz Boulevard",
        "type": "Boulevard"
      },
      "centre": {
        "utm": {
          "zone": "14U",
          "x": 630170,
          "y": 5519519
        },
        "geographic": {
          "latitude": "49.81398",
          "longitude": "-97.19061"
        }
      }
    },
    "route-schedules": [
      {
        "route": {
          "key": 94,
          "number": 94,
          "name": "Route 94 Whyte Ridge - Fort Garry",
          "customer-type": "regular",
          "coverage": "regular"
        },
        "scheduled-stops": [
          {
            "key": "11245829-34",
            "cancelled": "false",
            "times": {
              "arrival": {
                "scheduled": "2019-05-20T17:44:10",
                "estimated": "2019-05-20T17:43:15"
              },
              "departure": {
                "scheduled": "2019-05-20T17:44:10",
                "estimated": "2019-05-20T17:43:15"
              }
            },
            "variant": {
              "key": "94-0-H",
              "name": "to Henlow & Scurfield"
            },
            "bus": {
              "key": 211,
              "bike-rack": "false",
              "wifi": "false"
            }
          },
          {
            "key": "11245818-34",
            "cancelled": "false",
            "times": {
              "arrival": {
                "scheduled": "2019-05-20T18:27:10",
                "estimated": "2019-05-20T18:27:10"
              },
              "departure": {
                "scheduled": "2019-05-20T18:27:10",
                "estimated": "2019-05-20T18:27:10"
              }
            },
            "variant": {
              "key": "94-0-H",
              "name": "to Henlow & Scurfield"
            },
            "bus": {
              "key": 211,
              "bike-rack": "false",
              "wifi": "false"
            }
          }
        ]
      }
    ]
  },
  "query-time": "2019-05-20T17:33:44"
}
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
NotSoSure
  • 117
  • 2
  • 10
  • There are several types of fetch/API calls here, but you seem to have given JSON for only one of them, and it's not clear which it belongs to. It might be useful to verify that the data you're getting is correct at each stage of your process. – Khauri May 20 '19 at 23:19
  • To clarify, based on your code it would seem as if `console.log(response)` inside `addDataToHtml` would log an array, but the JSON you've given is not an array. – Khauri May 20 '19 at 23:20
  • Why is `addDataToHtml` resolving Promises? You already have the Object. Of course, I have to wonder why getting these results should take two separate `fetch`es in the first place. Are you sure you go to MIT? – StackSlave May 20 '19 at 23:25
  • Yes `console.log(response)` is an array and if I do ` response.forEach(e =>{ console.log(e); }) ` it gives me a seprate object of different bus stops. which I intend to do. – NotSoSure May 20 '19 at 23:28

1 Answers1

0

Along with Khauri McClain, I have a feeling that part of the issue is that you expect an array of JSON values. If you've only included the JSON for one of these array values, then it's not a real problem.

My other concern is that the .map isn't JSON decoding the full object. It may only be decoding the first level, so that "stop", "route-schedules", etc. are all still strings.

React - how to map nested object values?

As the above link describes, you may need to nest your .map s to get everything. As you have quite the nested object, you may want to make this recursive to get everything, without having to do it manually.

Or, you can just use JSON.parse() which does this automatically in a single call.

Edit:
You shouldn't have to do JSON.parse inside of the .map, you should be doing it instead of the .map.

Parse JSON in JavaScript?

https://www.w3schools.com/jsref/jsref_parse_json.asp

I'm borrowing this from the W3Schools TryIt example, but run this in your DevTools/console on your browser and just play around with it a little:

var obj = JSON.parse('{"firstName":"John", "lastName":"Doe", "nested":{"testing":40}}');

document.getElementById("demo").innerHTML = obj.firstName;
document.getElementById("demo").innerHTML += obj.nested.testing;

This should ouput:

John40

Just shove your whole Json object at JSON.parse and see what comes out. I don't think it'll handle the array of objects you're getting, but give it a try.

Also, after a little testing, you may not even need the response.map( e => e.json()) at all, as response may already be a Json object. I've tried to .json and JSON.parse objects that are already Json objects, and neither method returns any results. You may be doing too much.

At this point, I'd suggest doing a console.log of your variables or, better yet, assigning them to a window variable so you can use them in the console for manual testing:

window.r = response;

When I don't know what structure I'm dealing with, I do this a lot. It lets me play with things that should work in the code. Granted, not all ReactJS, JQuery, or other libraries all work in the DevTools console, but it's still a pretty good gauge of what is and isn't a thing.

computercarguy
  • 2,173
  • 1
  • 13
  • 27
  • Yes, you are right about the map function. so I tired `response.json()` on each element manually and it worked fine. But when I tried to do json.parse() in map function `response.map( e => JSON.parse(e))` it gives me error. I think JSON.parse works on XHR response, not on fetch response. I might be wrong here. Can you show me how to use JSON.parse() in map function with fetch response if it is useable in fetch request? – NotSoSure May 21 '19 at 00:05