Completely new to socket io here.
I want to emit data running from within a loop that I am running on my server. The loop runs for a while (a few seconds, up to a few minutes) and I want to emit data from my node server, that I then want to visualize on the client side in the browser (with chart js). Basically real time data charting.
The problem that occured is that apparently the emits are only fired after the loop has finished. From my understanding that is, because the emit function is asynchronous (non-blocking). And since the loop itself blocks until it is finished (originally used a while loop), the asynchronous calls are only fired afterwards. Correct?
while (CONDITION) {
...
io.emit('data update', DATA);
}
Now I have come up with my own solution, but it feels clonky. And I am wondering if there are better, more by the book ways to do this. What I am doing now is calling the loop step (where in the end I call emit) recursively as the callback to a setTimeout() with duration set to 0.
function loopStep() {
if (CONDITION) {
...
io.emit('data update', DATA);
setTimeout(loopStep,0)
}
}
setTimeout(loopStep,0);
My question is, are there other, better ways?
EDIT:
I was asked to add the full code.
Here is the full code code with the earlier (loop) version (as far as I can remember it, had to quickly reconstruct it here):
let stp = 0;
while (stp < maxLogStep) {
let new_av_reward;
var smallStep = 0;
while (smallStep < maxSmallStep) {
let ran1 = get_random();
let cum_prob = 0;
let chosen_action = pref.findIndex((el, i) => {
let pro = prob(i);
let result = pro + cum_prob > ran1;
cum_prob += pro;
return result;
})
let cur_reward = get_reward(chosen_action);
if (stp*maxSmallStep + smallStep == 0) {
new_av_reward = cur_reward
} else {
new_av_reward = prev_av_reward + (cur_reward - prev_av_reward) / (stp * maxSmallStep + smallStep)
}
let cur_prob = prob(chosen_action);
pref.forEach((element, index, array) => {
if (chosen_action === index) {
array[index] = element + stepSize * (cur_reward - new_av_reward) * (1 - cur_prob)
} else {
array[index] = element - stepSize * (cur_reward - new_av_reward) * (cur_prob)
}
});
prev_av_reward = new_av_reward;
smallStep++
}
io.emit('graph update', {
learnedProb: [prob(0), prob(1), prob(2)],
averageReward: new_av_reward,
step: stp * maxSmallStep + smallStep
});
stp++
};
And here is the recursive function with setTimeout:
function learnStep(stp, prev_av_reward) {
let new_av_reward;
if (stp < maxLogStep) {
var smallStep = 0;
while (smallStep < maxSmallStep) {
let ran1 = get_random();
let cum_prob = 0;
let chosen_action = pref.findIndex((el, i) => {
let pro = prob(i);
let result = pro + cum_prob > ran1;
cum_prob += pro;
return result;
})
let cur_reward = get_reward(chosen_action);
if (stp*maxSmallStep + smallStep == 0) {
new_av_reward = cur_reward
} else {
new_av_reward = prev_av_reward + (cur_reward - prev_av_reward) / (stp * maxSmallStep + smallStep)
}
let cur_prob = prob(chosen_action);
pref.forEach((element, index, array) => {
if (chosen_action === index) {
array[index] = element + stepSize * (cur_reward - new_av_reward) * (1 - cur_prob)
} else {
array[index] = element - stepSize * (cur_reward - new_av_reward) * (cur_prob)
}
});
prev_av_reward = new_av_reward;
smallStep++
}
io.emit('graph update', {
learnedProb: [prob(0), prob(1), prob(2)],
averageReward: new_av_reward,
step: stp * maxSmallStep + smallStep
});
setTimeout(learnStep, 0, stp + 1, new_av_reward);
};