0

I'm new to node. I created a simple server. The idea is that at each request, this servers makes an http request to a Weather API, and when it gets the answer, it send the answer to the client. I think the server is sending the answer too fast. This is my code:

    var http = require("http");

    function getWeather()
    {
        var http2 = require("http");

        http2.get("http://api.openweathermap.org/data/2.5/weather?lat=48.914348&lon=2.300282&appid=blabla123456&units=metric", (resp) => {
            let data = '';
            var answer = '-';

            resp.on('data', (chunk) => {
                data += chunk;
            });

            resp.on('end', () => {
                answer += JSON.parse(data).name + ", " + JSON.parse(data).sys.country + "\n" +JSON.parse(data).main.temp + "C";
                return(answer);
            });
        }).on("error", (err) => {
            console.log("Error: " + err.message);
        });
    }

    function hi(){
        return(5);
    }

    http.createServer(function (request, resp) {
        resp.writeHead(200, {'Content-Type': 'text/plain'});
        resp.end("Answer: " + hi() + " " + getWeather());
    }).listen(8080);

    console.log('Server running');

As you see, function getWeather returns answer, and function hi returns 5. My server response is "Answer: 5 undefined", so the getAnswer() return isn't presented, but the hi() return is there.

In the console, answer is printed after my server's answer, and it is exactly what I want it to show, but just too late.

Hope you can help me to solve this :)

Thanks!

Eskombro
  • 72
  • 5
  • Nothing to do with your error, but you should `JSON.parse` only once. `const result = JSON.parse(data);` and then use: `result.name`, `result.sys.country`.... Your actual error is that `getWeather` is asynchronous, and you should wait until the request is done before calling: `resp.end`. Check the duplicate. – Marcos Casagrande Jun 11 '18 at 22:58
  • Duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Marcos Casagrande Jun 11 '18 at 22:59
  • 1
    Thanks for the advice, I'll optimise my JSON parsing ;) – Eskombro Jun 11 '18 at 23:25

1 Answers1

1

Because this event takes time to process, you cannot return it. Try using a callback instead!

function getWeather(callback)
    {
        var http2 = require("http");

        http2.get("http://api.openweathermap.org/data/2.5/weather?lat=48.914348&lon=2.300282&appid=blabla123456&units=metric", (resp) => {
            let data = '';
            var answer = '-';

            resp.on('data', (chunk) => {
                data += chunk;
            });

            resp.on('end', () => {
                answer += JSON.parse(data).name + ", " + JSON.parse(data).sys.country + "\n" +JSON.parse(data).main.temp + "C";
                callback(answer);
            });
        }).on("error", (err) => {
            console.log("Error: " + err.message);
        });
    }

Then for the http request

http.createServer(function (request, resp) {
        resp.writeHead(200, {'Content-Type': 'text/plain'});
        getWeather(function(data) {
            resp.end("Answer: " + hi() + " " + data);
        });
    }).listen(8080);

If you can't tell, this works by calling a function that is sent when the data is ready.

person
  • 88
  • 10
  • Works, it's perfect, thanks! So the idea is that the server receives a request, it calls my getWeather function, and as a parameter I pass a function that will make the resp.end() with my data when everything is done. Nice, thanks! – Eskombro Jun 11 '18 at 23:20
  • this is a relatively simple way of doing it. If you want to get better, id suggest trying to use promises, or even more advanced - using `async/await` – person Jun 13 '18 at 00:19