I was trying to implement an event loop. The purpose of the loop is simple:
I tried an implementation in Nodejs in the following manner:
function task(){
this.task = Array.prototype.shift.call(arguments);
this.state = 'unprocessed';
this.successCallback = null;
this.failureCallback = null;
}
task.prototype.afterThat = function(){
if(arguments.length > 1){
this.successCallback = Array.prototype.shift.call(arguments);
this.failureCallback = Array.prototype.shift.call(arguments);
}
}
task.prototype._loop = function(){
let ctx = this;
while(ctx.state === 'unprocessed'){ // Source of problem
setImmediate(this.task, function(){
// change ctx.state if needed
}, function(){
// change ctx.state to 'processed'
});
}
}
The differences between this implementation and that of an event loop are as follows:
I believe the problem is the setImmediate invocation which, cannot change the context state because, the current execution state never terminates and keeps adding a new call for the same task in the event queue.
I hope I have explained it well and would appreciate some guidelines for implementation and, any errors that I may have in my understanding of the event queue.
Thanks.
Your while
loop is an infinite loop. JS is single threaded and thus nothing else can run until your while
loop finishes. Because nothing else can run, ctx.state
will never change. Because ctx.state
can never change, your while
loop runs forever.
Each time the loop runs it calls setImmediate()
which schedules a task to run, but that task can't actually run until the while
loop finishes. Thus you're deadlocked and you will be piling up a massive list of tasks to run (eventually overflowing some system resource probably).
You need to check ctx.state
after you complete running a task (probably in the success and failure callbacks), not in a loop like this.
setImmediate()
is not blocking. The function you schedule with setImmediate()
does not run until your while
loop is done, but that while
loop never finds its condition so it never stops because nothing else can run until the while
loop is done.
Instead, call the next task and when that is complete, then check ctx.state
. Since you don't show or describe how this is used or what you're really trying to accomplish, I'm unsure the best implementation to suggest. If you want more help with that, then you need to show us a lot more about what you're trying to accomplish and how you want to use this class.
My guess is that you could use promises to accomplish what you're trying to do without having to write much infrastructure code yourself at all since promises are very good tools for sequencing asynchronous tasks.
FYI, there are several things wrong with your code, such as missing closing braces and parens. What you have posted will not even parse correctly, much less run. And, please indent code properly when posting.