One of the commands in a discord bot I'm writing involves scraping a website using JSDom, waiting for its scripts to all run before reading the HTML. What I've found is that sometimes it takes a long time for that site's scripts to run, which causes the bot to become unresponsive for 3 minutes while it waits for the last query to finish. How can I make the action of scraping into an asynchronous function, so that the bot can still respond to other messages while it waits for the first call to finish?
This is a much-simplified version of my current code:
client.on('message', message => {
// command1 - the web scraper
console.log("benchmark A");
jsdom.JSDOM.fromURL(link, {resources: "usable", runScripts: "dangerously"}).then(dom => {
console.log("benchmark B");
dom.window.document.addEventListener('DOMContentLoaded', () => {
console.log("benchmark C");
setImmediate(() => {
console.log("benchmark D");
// read the DOM and do stuff with it
message.channel.send(some_value_from_dom);
});
});
});
// command2
// command3
// command4
// etc.
});
You can see I included some log statements. When someone calls command1, what happens in the console is that benchmarks A, B, C all show up almost immediately, but then benchmark D takes up to 3 minutes to appear. The main problem that I'm having is that, in that time between benchmark C and benchmark D, nobody else can query my bot. So I want to move the webscraping portion of the code into its own asynchronous function somehow, so that it can run in the background and not hold up the main block, thereby letting others continue to use the bot while this time-consuming command is processed. But I have no clue how to go about doing this in NodeJS since JavaScript doesn't support multithreading.