node.jsexpressejsyahoo-weather-api

Yahoo Weather API throws 'forEach' error


i decided to go ahead and use the yahoo weather api, in an attempt for it to show the location and then the weather.

app.js code:

** note i replaced the api url location with the term 'query'**

var express = require("express");
var app = express();
var request = require("request");

app.set("view engine", "ejs");


app.get("/", function(req, res){
    res.render("weatherSearch"); 
});

app.get("/results", function(req, res){
   var query = req.query.searchTerm;
   var url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22"+query+"%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"

   request(url, function(error, response, body){
            if(!error && response.statusCode == 200){
                var data = JSON.parse(body);
                res.render("results", {data: data});
            }
   });
});


app.listen(process.env.PORT, process.env.IP, function(){
   console.log("Server Connected"); 
});

weatherSearch.ejs :

<h1>Where would you like to check the weather?<h1>

<form action ="/results" method="GET">

    <input type="text" placeholder="Enter the city here!" name="searchTerm">
    <input type="submit">


</form> 

results.ejs

<h1>The Weather is:</h1>

<ul>
    <% data["query"].forEach(function(weather){ %>
    <li>
        <strong>
            <% weather["location"] %>
        </strong>
    </li>
<% }) %>

</ul>

<a href="/">Search Again!</a>

The error i receive from the console is:

Server Connected
TypeError: /home/ubuntu/workspace/WeatherSearchAPP/views/results.ejs:4
    2| 
    3| <ul>
 >> 4|     <% data["query"].forEach(function(weather){ %>
    5|     <li>
    6|         <strong>
    7|             <% weather["location"] %>

data.query.forEach is not a function
    at eval (eval at compile (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/ejs/lib/ejs.js:618:12), <anonymous>:11:22)
    at returnedFn (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/ejs/lib/ejs.js:653:17)
    at tryHandleCache (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/ejs/lib/ejs.js:251:36)
    at View.exports.renderFile [as engine] (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/ejs/lib/ejs.js:482:10)
    at View.render (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/express/lib/view.js:135:8)
    at tryRender (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/express/lib/application.js:640:10)
    at EventEmitter.render (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/express/lib/application.js:592:3)
    at ServerResponse.render (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/express/lib/response.js:1008:7)
    at Request._callback (/home/ubuntu/workspace/WeatherSearchAPP/app.js:19:21)
    at Request.self.callback (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/request/request.js:185:22)

yahoo weather api: (This currently gives the weather in 'london'), so if you copy this in to your web browser you'll see a vast amount of info pertaining to the weather in London.

https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22london%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys

if anyone has any suggestions on what i have done incorrectly that would greatly be appreciated!!


Solution

  • 'forEach' is an array method and the Yahoo Weather API doesn't return an array under the key "query". Each API is different, and each request can yield different structured JSON data.

    You can check how Yahoo Weather API response is structured by opening this link, as you mentioned. For example, if you want to access the city name, you would use

     <%= data.query.results.channel.location.city %>
    

    You get a forecast array returned for the upcoming days, on which you could use a forEach loop because it's an array: query.results.channel.item.forecast

    In a scenario where you would want to loop over objects in JS, you can use the for...in loop: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in