I'm trying to make a simple task queue with setInterval with a linked-list. I created a class with linkedlist and a setInterval function will keep calling a member function to consume the job.
function job_queue(){ this.job = null; this.pointer = this.job; this.job_dispatcher = null; this.length = 0; } job_queue.prototype.add_job = function( job ){ if( this.job == null ){ console.log('1st'); this.job = { job:job, next:null }; this.pointer = this.job; this.length = 1; }else{ console.log('2nd'); this.pointer.next = { job:job, next:null }; this.pointer = this.pointer.next; this.length++; } }; job_queue.prototype.event_handler = function(){ if( typeof this.job['job'] == 'undefined'){ console.log('??'); } if( this.job.job != null ){ console.log('hi'); this.job.job(); this.job = this.job.next(); } } job_queue.prototype.start_dispatch = function(){ if( this.job_dispatcher == null ){ console.log( this.event_handler ); this.job_dispatcher = setInterval( this.event_handler,1000); } } var jq = new job_queue(); function a(){ console.log('hi'); }; function b(){ console.log('hi2'); } jq.add_job(a); jq.add_job(b); jq.add_job(a); jq.start_dispatch();
However, when the event_handler function gets called , the program crashes with the log
if( typeof this.job['job'] == 'undefined'){
It seems like it can not access the member variable by calling member function with setInterval. I would like to ask what exactly happened with these lines of code and how can I achieve the goal?
As others have pointed out, setInterval()
calls your function in a different context. This means that the value of this
within the function passed to setInterval()
(in this case, event_handler()
) will not be pointing to the correct object.
A great solution to this problem is JavaScript's bind
function :
this.job_dispatcher = setInterval(this.event_handler.bind(this), 1000);
setInterval()
doesn't work with this
. See here: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval#The_this_problem
Code executed by setInterval() is run in a separate execution context to the function from which it was called. As a consequence, the this keyword for the called function will be set to the window (or global) object, it will not be the same as the this value for the function that called setTimeout.
You can call your method inside an anonymous function like this:
function job_queue(){ this.job = null; this.pointer = this.job; this.job_dispatcher = null; this.length = 0; } job_queue.prototype.add_job = function( job ){ if( this.job == null ){ console.log('1st'); this.job = { job:job, next:null }; this.pointer = this.job; this.length = 1; }else{ console.log('2nd'); this.pointer.next = { job:job, next:null }; this.pointer = this.pointer.next; this.length++; } }; job_queue.prototype.event_handler = function(){ if( typeof this.job['job'] == 'undefined'){ console.log('??'); } if( this.job.job != null ){ console.log('hi'); this.job.job(); this.job = this.job.next(); } } job_queue.prototype.start_dispatch = function(){ var self = this; if( this.job_dispatcher == null ){ console.log( this.event_handler ); this.job_dispatcher = setInterval( function(){self.event_handler()},1000); } } var jq = new job_queue(); function a(){ console.log('hi'); }; function b(){ console.log('hi2'); } jq.add_job(a); jq.add_job(b); jq.add_job(a); jq.start_dispatch();
If you console.log(this)
in the event_handler
, you'll see that this
points to the Window
object . This is because it is being called in setInterval
.
job_queue.prototype.event_handler = function(){
console.log(this); // <--- A Window object
if( typeof this.job['job'] == 'undefined'){
console.log('??');
}
if( this.job.job != null ){
console.log('hi');
this.job.job();
this.job = this.job.next();
}
}
One workaround for it would be to store the job_queue
reference as self
, and then call setInterval
as follows:
var self = this;
this.job_dispatcher = setInterval(function() {
self.event_handler();
}, 1000);
Code snippet:
function job_queue(){ this.job = null; this.pointer = this.job; this.job_dispatcher = null; this.length = 0; } job_queue.prototype.add_job = function( job ){ if( this.job == null ){ console.log('1st'); this.job = { job:job, next:null }; this.pointer = this.job; this.length = 1; }else{ console.log('2nd'); this.pointer.next = { job:job, next:null }; this.pointer = this.pointer.next; this.length++; } }; job_queue.prototype.event_handler = function(){ console.log(this); if( typeof this.job['job'] == 'undefined'){ console.log('??'); } if( this.job.job != null ){ console.log('hi'); this.job.job(); this.job = this.job.next(); } } job_queue.prototype.start_dispatch = function(){ if( this.job_dispatcher == null ){ console.log( this.event_handler ); var self = this; this.job_dispatcher = setInterval(function() { self.event_handler(self); },1000); } } var jq = new job_queue(); function a(){ console.log('hi'); }; function b(){ console.log('hi2'); } jq.add_job(a); jq.add_job(b); jq.add_job(a); jq.start_dispatch();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.