Express sends the answer before you have all the information you need

Asked

Viewed 33 times

-1

I am trying to make a tool just for my personal use, it is a WHOIS/ DNS search tool, and I use the API of another site to do this.

The URL I’m using to make the request is: http://www.isptools.com.br/tool.whois_json.php?query=

And you can put whatever you want after the URL that will be consulted.

My program collects the data successfully, but it sends back the "res" before the whois information is back, so the variable is Undefined.

function whois(ip) {
    var content;
    fetch('http://www.isptools.com.br/tool.whois_json.php?query='+ip)
        .then(res => res.json())
        .then(data => content = data)
        .then((content) => {
            console.log(content); // returns the actual data
            return content; // I have two of these just for testing purposes
        })
    return content; // :)
}

app.get("/query/:type/:ip",(req,res) => {
    var type = req.params.type;
    var ip = req.params.ip;
    var dados = 'nada';
    if (type === 'whois') {
        try {
            dados = whois(ip);
        } catch(err){
            console.log("Um erro ocorreu ao tentar fazer um query de WHOIS:\n"+err);
        }
    }

    console.log(dados); //returns undefined.
    res.send(dados); // returns a blank html
});

How can I do this the right way? I have no idea.

Thank you very much!

  • I’m Sorry if I Did Something Wrong on the posting part or Something Idiot on the code... Why I’m Betting down voted?

  • In [en.so] you should ask at Português

  • makes perfect sense, sorry... I had not seen that I was in Brazilian... I changed the language of the question

1 answer

1

You need to manipulate the response data within the callback call resolution to API.

Remember that these callbacks are not executed sequentially, they are triggered by events, so you can’t guarantee that they will be able to initialize a variable before its function returns this variable.

This topic of asynchrony is a little extensive, and you can find dozens of answers and topics about it, so I’m not going to waste a lot of time detailing how it works, I’m going to suggest some forms of resolution:

Return the Precedent of your function instead of the value

This way you can create a callback within your route /query/:type/:ip to handle when to invoke the res.send:

function whois(ip) {
    return fetch('http://www.isptools.com.br/tool.whois_json.php?query='+ip)
        .then(res => res.json())
        .then(content => {
            console.log(content);
            return content;
        });
}

app.get('/query/:type/:ip', (req, res) => {
    const type = req.params.type;
    const ip = req.params.ip;
    const promise = type === 'whois' ? whois(ip) : Promise.resolve();

    promise
        .then(dados => {
            console.log(dados);
            res.send(dados);
        })
        .catch(err => {
            console.log('Um erro ocorreu ao tentar fazer um query de WHOIS:\n'+err);
            res.status(500).send({ error: 'Algo deu errado' });
        });
});

Use async and await to write the code imperatively

This is a well-documented resource worth studying:

async function whois(ip) {
    const res = await fetch('http://www.isptools.com.br/tool.whois_json.php?query='+ip);
    const content = await res.json();

    console.log(content);
    return content;
}

app.get('/query/:type/:ip', async (req, res) => {
    const type = req.params.type;
    const ip = req.params.ip;

    try {
        const dados = type === 'whois' ? await whois(ip) : undefined;
        console.log(dados);
        res.send(dados);

    } catch (err) {
        console.log('Um erro ocorreu ao tentar fazer um query de WHOIS:\n'+err);
        res.status(500).send({ error: 'Algo deu errado' });
    }
});

Both approaches are equivalent.

  • Thank you very much!!! was exactly what I needed to know, I will research more on the subject from this =)

Browser other questions tagged

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