简体   繁体   中英

How to make synchronous DNS requests in a nodejs script?

I need to make synchronous DNS requests in my NodeJS program, using a specific DNS server (I need actual requests, no lookup). I would like to use the standard DNS library if possible. My code works in interactive mode but not in the actual script. I'm not very comfortable with sync issues so I don't fully understand what await and stuff actually do.

Here is my code, currently in my script:

var readline = require('readline-sync');

async function sendm(req, srv) {
    console.log("Will ask " + srv.getServers()[0] + " for " + req);
    const addresses = await srv.resolve4(req);
    console.log(addresses);
}

That function is executed when the user inputs something starting with "s":

const { Resolver } = require('dns').promises;
const dns = new Resolver();
dns.setServers(["8.8.8.8"]);
// ...

var input = "";
while(input != "q") {
        input = readline.question("Command: ");
        if(/^s/g.test(input)) { // input starts with s
                console.log("Input starts with s");
                sendm("stackoverflow.com", dns);
        }
        else if(/^r/g.test(input))
                console.log("input starts with r");
        // ...
}

Here is an output:

# nodejs debug.js
Command: s
Input starts with s
Will ask 8.8.8.8 for stackoverflow.com
Command: s
Input starts with s
Will ask 8.8.8.8 for stackoverflow.com
Command: s
Input starts with s
Will ask 8.8.8.8 for stackoverflow.com
Command: r
input starts with r
Command: r
input starts with r
Command: s
Input starts with s
Will ask 8.8.8.8 for stackoverflow.com
Command: q
[ '151.101.1.69', '151.101.65.69', '151.101.129.69', '151.101.193.69' ]
[ '151.101.1.69', '151.101.65.69', '151.101.129.69', '151.101.193.69' ]
[ '151.101.1.69', '151.101.65.69', '151.101.129.69', '151.101.193.69' ]
[ '151.101.1.69', '151.101.65.69', '151.101.129.69', '151.101.193.69' ]

I need to process the DNS addresses while the program is still running. How could I do? I've tried different things I found on the DNS library documentation but nothing worked. Could you please help me?

Thanks a lot!

Basically you need to make your while loop wait on the return of your function sendm I think you can put async before the while loop and then await before your function, although instead of storing the result in addresses it should be returned by the function (sendm) that way it will return a resolved promise and only then continue. If you cant wrap the while in async just stick it in a function and put the await before the function call to sendm . To be clear, async means the function is executed asynchronously, await means that it returns a resolved promise and will not continue execution until it reached that state of resolution. So it's kind of like having blocking synchronous code inside of an asynchronous function.

Being an async function, sendm returns a promise, but the while loop just starts again because it is not aware of promises and you can send a new request while the other is suspended on it's await call.
While top level await is not yet shipped with node you can wrap the whole thing in an async IIFE which will properly wait for your dns call.

(async () => {
        var input = "";
        while(input != "q") {
                // ...
                        await sendm("stackoverflow.com", dns);
                // ...
        }
})();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM