Home > Back-end >  I'm trying to fetch data from 3 apis but I can't. The first api returns data successfully
I'm trying to fetch data from 3 apis but I can't. The first api returns data successfully

Time:10-26

I'm building a web app using Node, Express, Cors and Body Parser. The app uses the fetch api to fetch data from online apis. Now I have written all the code with a server.js file, an index.html and an app.js. My server.js file contains the express server functions and middleware. My app.js contains the main functionality. Here are my files:

Index.html:

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Weather Journal</title>
</head>

<body>
  <div id="app">
    <div >
      Weather Journal App
    </div>
    <form id="userInfo">
      <div >
        <label for="zip">Enter City here</label>
        <input type="text" id="city" placeholder="enter city here" required>
      </div>
      <div >
        <label for="date">Enter departure date</label>
        <input type="datetime-local" id="date" required>
        <button id="submitBtn" type="submit"> Generate </button>
      </div>
    </form>
    <div >
      <div >Most Recent Entry</div>
      <div id="entryHolder">
        <div id="lat"></div>
        <div id="lng"></div>
        <div id="countryName"></div>
        <div id="temp"></div>
      </div>
    </div>
  </div>
  <script src="app.js" type="text/javascript"></script>

</body>

</html>

My app.js:

const geoURL = "http://api.geonames.org/searchJSON?";
const geoUsername = `rohanasif1990`;
const weatherURL = "https://api.weatherbit.io/v2.0/forecast/daily?"
const weatherKey = "20028a8267a24bba9a807362767bc4a7"

let d = new Date();
let newDate = d.getMonth()   1   "."   d.getDate()   "."   d.getFullYear();


const submitBtn = document.getElementById("submitBtn");

submitBtn.addEventListener("click", (e) => {
    e.preventDefault();
    const city = document.getElementById("city").value;

    if (city !== "") {
        getCity(geoURL, city, geoUsername)
            .then(function (data) {
                getWeather(weatherURL, weatherKey, data["geonames"][0]['lat'], data["geonames"][0]['lng'])
            }).then(weatherData => {
                postWeatherData("/addWeather", { temp: weatherData })
            }).then(function () {
                receiveWeatherData()
            }).catch(function (error) {
                console.log(error);
                alert("Invalid city");
            })
    }
})

const getCity = async (geoURL, city, geoUsername) => {
    const res = await fetch(`${geoURL}q=${city}&username=${geoUsername}`);
    try {
        const cityData = await res.json();
        return cityData;
    }
    catch (error) {
        console.log("error", error);
    }
}


const postWeatherData = async (url = "", data = {}) => {
    const response = await fetch(url, {
        method: "POST",
        credentials: "same-origin",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({
            temp: data.temp
        })
    });

    try {
        const newData = await response.json();
        return newData;
    }
    catch (error) {
        console.log(error);
    }
}

const receiveWeatherData = async () => {
    const request = await fetch("/allWeather");
    try {
        const allData = await request.json()
        document.getElementById("temp").innerHTML = allData.temp;
    }
    catch (error) {
        console.log("error", error)
    }
}

const getWeather = async (weatherURL, weatherKey, lat, lon) => {
    const res = await fetch(`${weatherURL}&lat=${lat}&lon=${lon}&key=${weatherKey}`);
    try {
        const weatherData = await res.json();
        return weatherData;
    }
    catch (error) {
        console.log("error", error);
    }
}

My server.js:

// Setup empty JS object to act as endpoint for all routes
cityData = {};
weatherData = {};
picturesData = {};

// Require Express to run server and routes
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');

// Start up an instance of app
const app = express();

/* Middleware*/
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// Cors for cross origin allowance
app.use(cors())
// Initialize the main project folder
app.use(express.static('website'));

app.get("/all", function sendData(req, res) {
    res.send(cityData);
})

app.get("/allWeather", function sendWeather(req, res) {
    res.send(weatherData);
})

app.get("allPictures", function sendPictures(req, res) {
    res.send(picturesData);
})

app.post("/add", (req, res) => {
    projectData['lat'] = req.body.lat;
    projectData['lng'] = req.body.lng;
    projectData['countryName'] = req.body.countryName
    res.send(cityData);
})

app.post("/addWeather", (req, res) => {
    weatherData['temp'] = req.body.temp;
    res.send(weatherData);
})

app.post("/addPicture", (req, res) => {
    picturesData['pic'] = req.body.pic;
    res.send(picturesData);
})

// Setup Server
app.listen(3000, () => {
    console.log("App listening on port 3000")
    console.log("Go to http://localhost:3000")
})


I am trying to get the geonames api to fetch the latitude and longitude of a city . Then I want to use the latitude and longitude to fetch the weather for that location. The pictures api is not implemented yet. I just want to use the data fetched from one api (geonames.org) as input to the other api (weatherbit.io). Right the app returns undefined when I console.log the final data.

CodePudding user response:

You are breaking the Promise then chain. You do not return any promise so that it can be chained. Pasting modified example withe capital RETURN statements

        getCity(geoURL, city, geoUsername)
            .then(function (data) {
                RETURN getWeather(weatherURL, weatherKey, data["geonames"][0]['lat'], data["geonames"][0]['lng'])
            }).then(weatherData => {
                RETURN postWeatherData("/addWeather", { temp: weatherData })
            }).then(function () {
                RETURN receiveWeatherData()
            }).catch(function (error) {
                console.log(error);
                alert("Invalid city");
            })

A better would be to write the function as Async, I see you have done that already

So

submitBtn.addEventListener("click", async (e) => {
    e.preventDefault();
    const city = document.getElementById("city").value;

    if (city !== "") {
      try {
        const city = await getCity(geoURL, city, geoUsername);
        const weatherData = await getWeather(weatherURL, weatherKey, city["geonames"][0]['lat'], city["geonames"][0]['lng']);
     
         //and so on
      } catch (e) {
         console.log(error);
         alert("Invalid city");
      }

    }
})

CodePudding user response:

The problem was here:

const receiveWeatherData = async () => {
    const request = await fetch("/allWeather");
    try {
        const allData = await request.json()
        document.getElementById("temp").innerHTML = allData['temp'];
    }
    catch (error) {
        console.log("error", error)
    }
}

I replaced allData['data'] with allData['temp']

  • Related