'How to continuously run your main code and also listen for new data and include it in your main code without blocking the main Thread?
I'm new to JavaScript and any assistance would be greatly appreciated. A simpler version of the code is shown below. I want to run a while loop that listens for new transactions via sockets and uses them in my while loop.
The issue is that if I don't leave the call stack, I'll never be able to add anything from the callback queue to the call stack. I tried using setInterval(()=>/code here,0), but that didn't help unless I added a 10-20 second time interval. Code in the while loop is CPU intensive. For e.g. if while loop takes 60 seconds to complete, setInterval will add a large number of callbacks in the callback queue which means those sockets messages are there somewhere in the callback queue but I will get them after a long period of time because first, it will run all the callbacks added by setInterval and this continuous.
A Task in the While loop process is CPU intensive, I figured that moving it to the worker thread might help, but I have to pass those transactions to the worker Thread as well, and because of the infinite while loop problem remains the same.
It is clear that I cannot use an infinite while loop. Is there any better approach to handle this?
const io = require("socket.io")(3700, { cors: { origin: "*" } });
const list = [];
class Blockchain {
constructor() {
this.unConfirmedTxs = [];
}
// Listen for new Unconfirmed Txs
startServer() {
io.on("connection", (socket) => {
console.log(`User is connected ${socket.id}`);
socket.emit("message", "Hello from server");
socket.on("sendTx", (data) => {
this.unConfirmedTxs.push(data);
console.log(this.unConfirmedTxs);
});
});
}
async main() {
this.startServer();
// Use UnconfirmedTxs here
while (true) {
console.log(this.unConfirmedTxs);
}
}
}
const blockchain = new Blockchain();
blockchain.main();
Answering my own question just in case someone else comes across this kind of issue. Here is how I solved this.
I solved this by using a recursive call. I have created an isReady flag and also used setTimeout instead of setinterval. After completion of my while loop, I am submitting asyncwhile as well in setTimeout({},0). In between if there are any messages it can listen asynchronously.
const io = require("socket.io")(3700, { cors: { origin: "*" } });
const list = [];
class Blockchain {
constructor() {
this.unConfirmedTxs = [];
this.isReady = false;
}
// Listen for new Unconfirmed Txs
startServer() {
io.on("connection", (socket) => {
console.log(`User is connected ${socket.id}`);
socket.emit("message", "Hello from server");
socket.on("sendTx", (data) => {
this.unConfirmedTxs.push(data);
console.log(this.unConfirmedTxs.slice(-20));
});
});
}
async addBlock() {
this.isReady = true;
console.log("Mining a Block");
setTimeout(() => {
this.asyncWhile();
}, 0);
}
async asyncWhile() {
if (this.isReady) {
this.isReady = false;
this.addBlock();
}
}
async main() {
this.isReady = true;
this.startServer();
// Use UnconfirmedTxs here
this.asyncWhile();
}
}
const blockchain = new Blockchain();
blockchain.main();
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
