1

I have a function A that performs a dns.reverse(ip) (using 'dns' js npm) to check if IP is used or not. If it throws an error its free. Most of IPs it works as expected as it throws error straight away, but problem is that some IPs do not, it waits for 1.2minutes to timeout.

var dns = require('dns')
async function A(ip){
try{
 var host = await dns.reverse(ip)
 if (host.length >1) //its used
}catch(e){
 // free ip if dns.reverse failed
}
}

Is there a way for me to limit execution time of the await dns.reverse(ip) to lets say 5seconds, so it doesnt wait the whole 1.20min and just throw an error if it takes longer than 5 seconds to lookup? Thanks!

Powisss
  • 1,072
  • 3
  • 9
  • 16

2 Answers2

2

You can use Promise.race() like this:

const dns = require('dns');

const timeout = (delay, message) => new Promise((_, reject) => setTimeout(reject, delay, message));

const delay = 5000;

async function A(ip) {
    try {
        const host = await Promise.race([dns.reverse(ip), timeout(delay, `DNS resolution timed out after ${delay} ms`)]);
        console.log(host);
    } catch (e) {
        console.error(e);
    }
}
Guerric P
  • 30,447
  • 6
  • 48
  • 86
  • Thank you I think this works now. Just a question. Because there is await in front of Promise, there is no need to have await in front of dns.reverse, it still 'awaits' for those 5 seconds for dns.reverse? is that correct? – Powisss Nov 30 '20 at 13:27
  • `dns.reverse(ip)` and `timeout(...)` both return promises, and `Promise.race` "concatenates" these two promises into one, and we `await` that promise. That supposes you have some more logic in the `A` function. If not, you can remove the `async` keyword and write this body: `return Promise.race([..., ...]).then(console.log).catch(console.error);` – Guerric P Nov 30 '20 at 13:31
  • Great, thank you again for help and explanation. Accepted as answer. – Powisss Nov 30 '20 at 13:34
1

Just for fun :) Cancellable version (aborts the related network request)

import CPromise from "c-promise2";
import dns from 'dns';

const reverseIP = (ip, ms) => new CPromise((resolve, reject, {onCancel}) => {
    const resolver = new dns.Resolver();
    resolver.reverse(ip, (err, hosts)=> err? reject(err) : resolve(hosts));
    onCancel(() => resolver.cancel())
}).timeout(ms);

reverseIP('216.58.214.206', 2000)
    .then(hosts=> console.log(`Host: ${hosts}`), err=> console.warn(`Fail: ${err}`));

const request= reverseIP('16.58.214.206', 2000)
    .then(hosts=> console.log(`Host: ${hosts}`), err=> console.warn(`Fail: ${err}`));

setTimeout(()=> request.cancel(), 100);

reverseIP('16.58.214.206', 2000)
    .then(hosts=> console.log(`Host: ${hosts}`), err=> console.warn(`Fail: ${err}`));

Output:

Host: bud02s23-in-f206.1e100.net,bud02s23-in-f14.1e100.net
Fail: CanceledError: canceled
Fail: CanceledError: timeout

Process finished with exit code 0
Dmitriy Mozgovoy
  • 1,419
  • 2
  • 8
  • 7