javascript - JS中这个异步循环有更好的实现吗?
问题描述
所以我正在编写一个 node.js 脚本,它使用 Playwright 在浏览器中以设定的时间间隔发送不同的消息。我遇到了脚本异步部分的问题。
我最初是这样设置的
async start() {
this.interval = setInterval(async () => {
await sendMessages(this.messages);
}, 1000);
}
我很确定await
关键字在这里什么都不做,只是在 1000 毫秒后执行下一次迭代,无论是否sendMessages
完成执行。这导致消息在达到再次发送的间隔要求时被双重发送。
此代码有效,并且是我的问题的主题:
async start() {
while (!this.stopFlag) {
await sendMessages(this.messages);
await timeout(1000);
}
}
timeout
是一个简单的函数,它在调用后解析一个 Promise setTimeout
。但是,这似乎有点老套,我不太喜欢这种实现方式。有没有人有更聪明的方法来执行这样的事情?
以下是更多代码细节:
Messenger.js
import Message from './Message.js'
import { timeout } from './Timeout.js'
export default class Messenger {
constructor(messages, page) {
this.page = page;
this.messages = messages.map((msg) => new Message(msg));
this.stopFlag = false;
}
async start() {
while (!this.stopFlag) {
await this.sendMessages();
await timeout(1000);
}
}
async sendMessages() {
for (const message of this.messages) {
if (message.shouldSend()) {
await message.send(this.page);
}
}
}
stop() {
this.stopFlag = true;
}
}
消息.js
export default class Message {
constructor(message) {
this.text = message.text;
this.timing = message.timing;
this.lastSent = null;
}
async send(page) {
logMessage(`Sending message "${this.text}" in channel.`);
await playwrightFunctionToSendMessage();
this.lastSent = new Date();
}
shouldSend() {
// returns a boolean based on this.timing and this.lastSent
}
}
解决方案
而不是stop
方法 reassigning this.stopFlag
,让它清除间隔或超时。
async start() {
if (this.timeoutId) return; // timeout is already running - don't start another
const startTimeout = () => {
this.timeoutId = setTimeout(() => {
this.sendMessages()
.then(() => {
if (this.timeoutId) startTimeout();
})
.catch(handleErrors); // don't forget this part
}, 1000); // 1 second between finish of last sendMessages and start of next
};
startTimeout();
}
stop() {
clearTimeout(this.timeoutId);
this.timeoutId = null;
}