Using Fetch to resolve data from 2 different apis

Hello Guys

Please let me start by saying hello and be gentle with me i’m new to Javascript.

I got it in my head to see if i could calculate the distance between 2 postcodes.

The following piece of code is rough and ready version and i’m not sure at all if i have got this right. Does the code follow convention or is it a mess and completely wrong. The code works up to the point of inserting the start and end coordinates to calculate the distance and return it back.

The post codes are returned with correct coordinates, but i also don’t know how to update the global variables for the start and end points at the top of the file.

Anyhow thanks for any input i appreciate it. I have removed my api keys and postcodes for security.

let calculateDistance = function(firstPostcode, secondPostcode) {

  const fetch = require("node-fetch");
  let start = "";
  let end = "";

  // Start Post Code
  fetch(`https://api.postcodes.io/postcodes/${firstPostcode}`)
    .then((response) => {
      return response.json()
    })
    .then((startPostcode) => {
      // Work with JSON data here
      let long = JSON.parse(startPostcode.result.longitude);
      let lat = JSON.parse(startPostcode.result.latitude);
      start = (long + ',' + lat);
      console.log(start);
    })
    .catch((err) => {
      // Do something for an error here
    });

  // End Post Code
  fetch(`https://api.postcodes.io/postcodes/${secondPostcode}`)
    .then((response) => {
      return response.json()
    })
    .then((endPostcode) => {
      // Work with JSON data here
      let long = JSON.parse(endPostcode.result.longitude);
      let lat = JSON.parse(endPostcode.result.latitude);
      end = (long + ',' + lat);
      console.log(end);
    })
    .catch((err) => {
      // Do something for an error here
    });

  // Calculate the distance
  fetch(`https://api.openrouteservice.org/v2/directions/driving-car?api_key=**********************************************&start=${start}&end=${end}`)
    .then((response) => {
      return response.json()
    })
    .then((getDistance) => {
      // Work with JSON data here
      let distance = JSON.parse(getDistance.features[0].properties.summary.distance);
      let miles = (distance/1609.344 + ' miles');
      console.log(miles);
    })
    .catch((err) => {
      // Do something for an error here
    });
}

calculateDistance('firstPostCode', 'secondPostCode');

Thanks

Simon

Hello @PenguinPowered , welcome to the forum.

Your code is not really following the actual async flow of the operations.
Please remember that Javascript doesn’t wait for an async operation to complete before moving forward unless specifically told so!

Consider this example:

fetch().then(console.log("a");
console.log("b").

The actual output will be:

"b"
"a"

Since fetch is returning a promise that gets completed later.

For example in your code you have 3 async operations, one of which depends on the success of the previous two. Both async operation can take any amount of time to finish or fail.
The flow should be something like:

start async operation one.
start async operation two.

-- only after both complete with success start the third async operation.

There is a great method called Promise.all that can really help in simplify your code:

Promise.all([fetch1, fetch2,]).then((values) => {
  // here values is an array of what's returned from your fetch.
 // for example you can have startJSON and endJSON.
 // you know that this block is executed when both fetch complete.

// do your thing
 fetch3(startJSON, endJSON)
}).catch(error => doSomethingWith(error));

Hope this helps :sparkles:

Hello Marmiz

Thanks very much for your reply, i knew i would have it all mixed up.

I’m going to have another go and see if i can clean it up with your suggestions.

Thanks again

Simon

Welcome, PenguinPowered.

I’ve edited your post for readability. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (’).

Hello Marmiz.

I’ve had another go at it and this is what i have below. It works as expected and a lot more streamlined. Thanks for your help.

let calculateDistance = function(firstPostcode, secondPostcode) {
    const fetch = require("node-fetch");

    Promise.all([
        fetch(`https://api.postcodes.io/postcodes/${firstPostcode}`),
        fetch(`https://api.postcodes.io/postcodes/${secondPostcode}`),
    ]).then(function (responses) {
        // Get a JSON object from each of the responses
        return Promise.all(responses.map(function (response) {
            return response.json();
        }));
    }).then(function (data) {
        // Pull out the longitude and latitide data for each postcode
        // Postcode 1
        let startLong = JSON.parse(data[0].result.longitude);
        let startLat = JSON.parse(data[0].result.latitude);

        // Postcode 2
        let endLong = JSON.parse(data[1].result.longitude);
        let endLat = JSON.parse(data[1].result.latitude);

        // Format the data into a useable type
        let start = (startLong + ',' + startLat)
        let end = (endLong + ',' + endLat)

        // Fetch the distance data for the two sets of coordinates
        fetch(`https://api.openrouteservice.org/v2/directions/driving-car?api_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&start=${start}&end=${end}`)
        .then((response) => {
            return response.json()
        })
        .then((getDistance) => {
            // Convert metres to miles
            let distance = JSON.parse(getDistance.features[0].properties.summary.distance);
            let m = (distance/1609.344);
            let miles = m.toFixed(2);
            console.log(miles + ' miles')
        })
    }).catch(function (error) {
        // if there's an error, log it
        console.log(error);
    });
}

calculateDistance('xxx xxx', 'xxx xxx');

Happy to help :sparkles: