[英]DiscordJS - asynchronously respond to messages
我正在编写的 discord 机器人中的命令之一涉及使用 JSDom 抓取网站,等待其脚本全部运行,然后再读取 HTML。 我发现有时该站点的脚本需要很长时间才能运行,这会导致机器人在等待最后一个查询完成时无响应 3 分钟。 如何将抓取操作变成异步 function,以便机器人在等待第一次调用完成时仍然可以响应其他消息?
这是我当前代码的简化版本:
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.
});
你可以看到我包含了一些日志语句。 当有人调用command1
时,控制台中发生的情况是基准测试 A、B、C 几乎立即显示,但随后基准测试 D 最多需要 3 分钟才会出现。 我遇到的主要问题是,在基准 C 和基准 D 之间的那段时间里,没有其他人可以查询我的机器人。 所以我想以某种方式将代码的网络抓取部分移动到它自己的异步 function 中,这样它就可以在后台运行而不阻塞主块,从而让其他人在处理这个耗时的命令时继续使用机器人. 但我不知道如何 go 关于在 NodeJS 中执行此操作,因为 JavaScript 不支持多线程。
多一点挖掘,我已经解决了我自己的问题。 我将网络抓取 function 放入一个工作线程中,每次我想运行它时,我都会将链接从主线程发布到工作线程,让它做它的事情,然后当它完成后将消息发布回主线程。
这是之前的代码:
// bot.js
client.on('message', message => {
jsdom.JSDOM.fromURL(link, {resources: "usable", runScripts: "dangerously"}).then(dom => {
dom.window.document.addEventListener('DOMContentLoaded', () => {
setImmediate(() => {
// read the DOM and do stuff with it
message.channel.send(some_value_from_dom);
});
});
});
});
这是它之后的样子:
// bot.js
const worker = new Worker('./worker.js');
client.on('message', message => {
// Construct link
worker.once('message', response => {
message.channel.send(response);
});
worker.postMessage(link);
});
// worker.js
parentPort.on('message', link => {
jsdom.JSDOM.fromURL(link, {resources: "usable", runScripts: "dangerously"}).then(dom => {
dom.window.document.addEventListener('DOMContentLoaded', () => {
setImmediate(() => {
// read the DOM and do stuff with it
parentPort.post(some_value_from_dom);
});
});
});
});
现在所有的网络抓取都是单独完成的,其他用户仍然可以同时查询机器人的其他命令,而无需等待几分钟来完成第一个任务。 也许我错过了一个更简单的解决方案,但是 a) 我不会声称自己是 JS 专家,并且 b) 这完全按照我想要的方式工作,所以我认为没有理由再次更改它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.