Frage

I have a text area that I am synchronizing with GoInstant. here is what the code looks like:

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

This creates an infinite loop, when updating one text field i.e. When changing the value of the textarea, this triggers a Platform key update, which in turn changes the value of the textarea infinitely ...

EDIT: Based on the top answer I came up with the following constructor:

function BounceProtection() {
  var remoteUpdate = false; // remote toggle
  this.local = function(cb) {
    if (remoteUpdate) return;
    cb();
  };
  this.remote = function(cb) {
    remoteUpdate = true;
    cb();
    remoteUpdate = false;
  };
}

This way, I can generate bounceProtection objects as needed to protect multiple keys even with the asynchronous nature of js.

var myKeyBP = new BounceProtection();
War es hilfreich?

Lösung

A quick method of preventing an infinite propagation loop:

// 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;
    });
  });
});

Andere Tipps

Simply remove the listener before editing the textarea and then reapply it (I also cached your textarea for you so you don't search the DOM on every triggered event).

I also suggest you give the textarea an ID attribute as it appears you are working with one textarea but doing a tag search which is inefficient and easily broken by adding another textarea to the page.

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

Another possible way is to compare values first before setting the value. Arguably not generic enough in the case where events do not have comparable values, but in this case this solution would work.

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;
  });
})
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top