-1

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!!

Prash
  • 150
  • 9
  • Your basic first step BEFORE coming to stack overflow is to do `console.log(data.query)` and see exactly what you have there. If it's not an array (which apparently it isn't), then duhhh, that's why`.forEach()` doesn't work on it. These are the simple debugging steps you should do before coming here. If you collect that kind of info and still don't understand what is wrong, then you post here and you include all the debugging steps you took and what you found in doing that. – jfriend00 Aug 03 '18 at 21:38

2 Answers2

1

The API returns data in the format of { "query": { ...} }, translate this into a JSON object and you end up with a query object, not an array. Looking at the query object itself it does seem to have count and results properties (and the results property also looks like an object). However, your particular query only yields a single result, so assuming this yields an array in scenarios where you have more than one I presume you'll need to use a combination both of these properties to parse the data accurately e.g.

const data = JSON.parse(body);
const { count, results } = data.query;
res.render("results", { 
  results: count > 1 ? results : [results]  // wrap in an array of only single result
});

Then in your view

<% results.forEach(...) %>
James
  • 80,725
  • 18
  • 167
  • 237
-1

'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

Prash
  • 150
  • 9