2015-09-03 5 views
3

Я пытаюсь создать простую очередь задач с setInterval со связанным списком. Я создал класс со связанным списком, и функция setInterval будет продолжать вызывать функцию-член, чтобы потреблять задание.Функция класса класса Javascript, вызывающая функцию-член setInterval, не могла получить доступ к переменной-члену

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();

Однако, когда функция event_handler вызывается, программа падает с бревна

if(typeof this.job['job'] == 'undefined'){ 

Похоже, он не может получить доступ к переменной-члена с помощью вызова функции-члена с setInterval. Я хотел бы спросить, что именно произошло с этими строками кода и как я могу достичь цели?

+0

Смотрите этот ответ для объяснения того, как 'работает this': http://stackoverflow.com/questions/13441307/how-does-the -this-keyword-in-javascript-act-in-a-object-literal/13441628 # 13441628 – slebetman

ответ

1

setInterval() не работает с this. Смотрите здесь: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval#The_this_problem

Код, выполняемый с помощью setInterval() выполняется в отдельном контексте выполнения к функции, из которой она была вызвана. Как следствие, это ключевое слово для вызываемой функции будет установлено в окне (или глобальном) объекте , оно не будет таким же, как это значение для функции , которая называется setTimeout.

Вы можете назвать свой метод внутри анонимной функции, как это:

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();

+0

Спасибо. Есть ли лучший способ написать очередь заданий без setInterval? – Jian

+0

А также в ссылке это.job_dispatcher = setInterval (function() {self.event_handler()}, 1000); Почему вызов self.event_handler() без упаковки в закрытие не работает? – Jian

+0

Я не уверен, какой был бы лучший подход для очереди. Может быть, посмотрим на обещания. Или вы можете просто иметь массив, в котором вы нажимаете задания и вызываете обработчик событий в add_job. В любом случае, я не думаю, что вам нужно setInterval. А что касается того, почему вызов self.event_handler работает только в анонимной функции: проблема не в том, что «this» в аргументе setInterval, это «это», которое назначается при выполнении функции. Он выполняет только функцию, которую вы предоставляете, и назначая это окно. –

0

Если вы console.log(this) в event_handler, вы увидите, что this points to the Window object. Это происходит потому, что он вызывается в 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(); 
     } 
} 

Один из способов для этого было бы хранить job_queue ссылку как self, а затем вызвать setInterval следующим образом:

var self = this; 
this.job_dispatcher = setInterval(function() { 
    self.event_handler(); 
}, 1000); 

Фрагмент кода:

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();

+0

Спасибо. Я новичок в javascript и понятия не имел, как правильно использовать некоторые функции. – Jian

2

Как и другие указали, setInterval() называет вашу функцию в . Это означает, что значение в функции, переданной в setInterval() (в данном случае event_handler()), не будет указывать на правильный объект.

Отличное решение этой проблемы в JavaScript bind function:

this.job_dispatcher = setInterval(this.event_handler.bind(this), 1000); 

 Смежные вопросы

  • Нет связанных вопросов^_^