Return of Request (Node.js)

Asked

Viewed 2,024 times

1

I’m trying to consume an API with request, but I’d like to know how to assign the return to a variable. Here’s my code:

var response
function getWeather() {
    request(url, function (error, response, body) {
        console.log(body)
        response = body
    })
}
console.log(response)

The console.log(body) returns the string value, but the console.log(Response) returns Undefined. I would like the Answer variable to capture the body content for me to manipulate. How can I do this?

  • You must put the console.log inside the callback. It is not recommended to try to remove a variable from within the scope of a callback call. You can better understand in that reply.

2 answers

2

Your "problem" consists of the fact that this request made by the module is asynchronous i.e.: the request will be made and subsequently you will get a reply, either the body of the request or an error that occurred in the request.

You are declaring a variable without a content (response) hoping to assign a value to it when the answer comes though, is accessing (using) this variable before it happens (console.log) ... will always be undefined

You must use a callback to work on this value, example:

const request = require("request");

function getWeather(callback) {
    request(url, function (error, response, body) {
        callback(body)
    })
}

getWeather(function(responseBody) {
    console.log(responseBody)
})

By default this module does not work with Promise() but as described by the module itself you can use the adjacent packages if you want to work on "Promises" see links of adjacent packages:

https://www.npmjs.com/package/request#Promises-asyncawait

If you don’t want to use extra packages know that you can do this natively using the native module utils and "promising" the request:

const util = require('util')
const request = require("request");

const requestPromise = util.promisify(request);

function getWeather(url) {
    return requestPromise(url).then(response => {
        if ( response.statusCode === 200 ) {
            return response.body
        }
        return Promise.reject(response.statusCode)
    })
}    

getWeather('https://www.google.com').then(body => {
    console.log(body)
}).catch(e => console.log(e))

Since not all possible status codes are an error in the request you should treat them as you really want them, the above example will only return the body of the request if the status is equal to 200 and reject all others.

Promise() by nature are "asynchronous" functions but you can use await to work on a "synchronous" behavior as long as it is within a function async:

const util = require('util')
const request = require("request");
const requestPromise = util.promisify(request);    


async function done() {
    let response = await requestPromise('https://www.google.com')
    console.log(response.body)
}    

done()

In the above example there is no guarantee that the answer will have a property "body" and cannot do any treatment in case of error/failure other than that all the code will "wait" for the order to complete and a server may take too long to respond.

A "better" approach would be to address possible gaps in the request in a block .catch():

const util = require('util')
const request = require("request");
const requestPromise = util.promisify(request);


async function done() {
    async function getWeather(url) {
        return requestPromise(url).then(response => {
            if ( response.statusCode === 200 ) {
                return response.body
            }
            return Promise.reject(response.statusCode)
        }).catch(err => {
            return err
        })
    }

    console.log(await getWeather('https://www.google.com'))
}

done()

reading:

Mozilla Docs: async/await

  • 1

    Perfect explanation, my dear! Actually I got a little lost in some Node concepts, I consumed the API perfectly in PHP which is much quieter, but I researched more about async and await and about the NODE itself and managed to understand and apply, and I also liked the approach you used on the issue of error handling of the request. The example is very complete and well taught! Thanks, and as soon as I finish I will do a tutorial on how I consumed the API for the next ones who have the same question.

1


The ideal is that you give a Return in the Weather that consumed by the API in the getWeather method and so use the getWeather method where you want.

For example:

async function getWeather() {
    return request(url, function (error, response, body) {
        if (response.status === 200)
           return body

        return false
    })
}

Note: I have not tested the code and I do not know if request solves a Promise, if it is may not work. But it is just to give you a notion.

Later you just call the function to consume the API and already get the value where you want.

const weather = await getWeather()

Understood the concept?

  • I believe there is a mistake in your example. await can only be called within the scope of a function async see the documentation Mozilla Docs: async/await ... and if it were the case getWeather() was async the return would be: Promise.resolve(body)

  • 1

    In the same way as a full example was not passed, I only gave a general explanation, since I never used and do not use the request. But when calling the function with await it is necessary to be inside an async, of course. It is that maybe the friend still does not know very well the headache of Node rsrs' asynchronousness even more consuming an API.. haha at least with the await there he could dig deeper. But the answer his reply was quite complete, he can use it almost completely in his example... I already gave a positive vote on it! =]

Browser other questions tagged

You are not signed in. Login or sign up in order to post.