Два синхронизированных события, создающие бесконечный цикл
У меня есть текстовая область, которую я синхронизирую с GoInstant. вот как выглядит код:
var myRoom = platform.room('myRoom');
var myKey = myRoom('myKey');
// Listen to set events on the platform key and update a textarea
myKey.on('set', function(textAreaContent) {
$('textarea').val(textAreaContent);
});
// When the textarea changes, set the platform key
$('textarea').on('change', function(){
var textAreaContent = $(this).val();
myKey.set(textAreaContent, function(err) {
if (err) throw err;
});
})
Это создает бесконечный цикл при обновлении одного текстового поля, т. Е. При изменении значения текстовой области, это вызывает обновление ключа платформы, что, в свою очередь, изменяет значение текстовой области бесконечно...
РЕДАКТИРОВАТЬ: На основе верхнего ответа я придумал следующий конструктор:
function BounceProtection() {
var remoteUpdate = false; // remote toggle
this.local = function(cb) {
if (remoteUpdate) return;
cb();
};
this.remote = function(cb) {
remoteUpdate = true;
cb();
remoteUpdate = false;
};
}
Таким образом, я могу создавать объекты bounceProtection по мере необходимости для защиты нескольких ключей даже при асинхронной природе js.
var myKeyBP = new BounceProtection();
3 ответа
Быстрый метод предотвращения бесконечного цикла распространения:
// Infinite loop prevention
var bounceProtection = {
remoteUpdate: false, // remote toggle
local: function(cb) {
if (this.remoteUpdate) return;
cb();
},
remote: function(cb) {
this.remoteUpdate = true;
cb();
this.remoteUpdate = false;
}
};
var myRoom = platform.room('myRoom');
var myKey = myRoom.key('myKey');
myKey.on('set', function(textAreaContent) {
bounceProtection.local(function() {
$('textarea').val(textAreaContent);
});
});
$('textarea').on('change', function(){
var textAreaContent = $(this).val();
bounceProtection.remote(function() {
myKey.set(textAreaContent, function(err) {
if (err) throw err;
});
});
});
Просто удалите прослушиватель перед редактированием текстовой области, а затем повторно примените ее (я также кэшировал вашу текстовую область для вас, чтобы вы не искали DOM при каждом вызванном событии).
Я также предлагаю вам присвоить атрибуту textarea атрибут ID, так как кажется, что вы работаете с одной текстовой областью, но выполняете поиск по тегам, который неэффективен и легко нарушается при добавлении другой текстовой области на страницу.
var myRoom = platform.room('myRoom');
var myKey = myRoom('myKey');
var $textarea = $('textarea');
function setKey() {
var textAreaContent = $(this).val();
myKey.set(textAreaContent, function(err) {
if (err) throw err;
});
}
// Listen to set events on the platform key and update a textarea
myKey.on('set', function(textAreaContent) {
$textarea.off('change', setKey); // Remove listener
$textarea.val(textAreaContent);
$textarea.on('change', setKey); // Reapply listener
});
// When the textarea changes, set the platform key
$textarea.on('change', setKey);
Другой возможный способ - сначала сравнить значения перед установкой значения. Возможно, недостаточно универсальный в случае, когда события не имеют сопоставимых значений, но в этом случае это решение будет работать.
myKey.on('set', function(textAreaContent) {
var $textarea = $('textarea');
if ($textarea.val() !== textAreaContent) { // compare values first
$textarea.val(textAreaContent);
}
});
// When the textarea changes, set the platform key
$('textarea').on('change', function(){
var textAreaContent = $(this).val();
myKey.set(textAreaContent, function(err) {
if (err) throw err;
});
})