2016-10-24 2 views
1

У меня есть ситуация, когда метод должен называть себя рекурсивно и асинхронно через setImmediate.«это» потеряно в setImmediate call?

Следующий код не имеет никакого отношения к оригиналу, но возникает одна и та же «проблема»: «эта» ссылка, по-видимому, теряется при втором вызове.

function A() { 
    this.some_message = 'Index is: '; 
} 

A.prototype.someMethod = function (index) { 
    console.log(`${this.some_message} ${index}`); 
    setImmediate(this.someMethod, index + 1); 
} 

У меня есть следующий вывод, в котором «this.someMethod», в какой-то момент перестает быть функцией, я не понимая его:

> new A().someMethod(1) 
Index is: 1 
undefined 
> undefined 2 
TypeError: "callback" argument must be a function 
    at exports.setImmediate (timers.js:664:11) 
    at Immediate.A.someMethod (repl:3:1) 
    at runCallback (timers.js:639:20) 
    at tryOnImmediate (timers.js:610:5) 
    at processImmediate [as _immediateCallback] (timers.js:582:5) 
> 

Я решил ее путем изменения последняя строка метода:

setImmediate(this.someMethod.bind(this), index + 1); 

Но я не понимаю, почему setImmediate ведет себя так. Может ли кто-нибудь предоставить мне ссылку? Я буду очень признателен за любую помощь. Я пару часов пытался найти ответ. Заранее спасибо.

- Редактировать: Также не стесняйтесь предлагать лучшее название или редакцию. У меня довольно плохой уровень английского.

+2

Read: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout#The_this_problem – epascarello

+0

Спасибо за это ... я смотрел на неправильном пути! –

ответ

3

Каждый раз, когда вы используете функции более высокого порядка, вы будете потерять контекст. У вас есть три варианта: сохранить ref в this в закрытии, связать функцию, которую вы передаете, или не использовать this.

// using Function.prototype.bind 
var foo = { value: 3 }; 
foo.method = function() { return this.value }; 

function doesAsync() { 
    setImmediate(foo.method.bind(foo)); 
} 

// using a closure 
var bar = { 
    value: 3, 
    method: function() { 
    var self = this; 
    setImmediate(function() { 
     alert(self.value); 
    }); 
    } 
}; 
+0

Я всегда избегаю «этого» ... но на этот раз я не могу .. хе. Спасибо :) Мне не хватает того, что setImmediate выполняется из другого контекста. –

+1

@ EmilioGrisolía. Да, и это произойдет каждый раз, когда вы передаете метод в качестве аргумента, к сожалению. Я стараюсь избегать «этого», но я также пишу google maps apps для жизни :) –

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