Sunday, November 23, 2014

Replacing MutationObserver with Object.observe() in Polymer


I was able to fix and test a change observer for Polymer
elements. Tonight, I am curious if the Object.observe() approach might offer any benefits over the current MutationObserver approach that I have been using in Patterns in Polymer.

Given a Polymer element (el), a form input object (input), and an attribute to watch on the Polymer element, I can ensure that the value of the form element synchronizes with the Polymer element thusly:
  var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
      if (mutation.attributeName == attr) {
        input.value = mutation.target[attr];
      }
    });
  });
  observer.observe(el, {attributes: true});
The observer watches el (including attribute changes). Each time changes are seen, the callback loops through the changes (mutations) looking for one that matches the attribute attr. Finding such a change, the callback then updates the form input field with the same value as the Polymer element.

This solution works just fine, but is a little cumbersome if only because MutationObserver is a lot to type.

So what about Object.observer()? It turns out that very little need change to support a switch to this new approach:
  Object.observe(el, function(changes){
    changes.forEach(function(change){
      if (change.name == attr) {
        input.value = change.object[attr];
      }
    });
  });
In fact, aside from less haughty "changes" in place of "mutations," almost nothing has changed. I still loop through the list of changes and conditionally update input. The only real difference is that I no longer have to create a mutation object that can then observe the element—the observe() code is baked right into Object.

It would be nice to filter out only those changes in which I am interested. Object.observe() does support filtering, but is limited to filters only the type of change, not the attribute being changed:
  Object.observe(el, function(changes){
    changes.forEach(function(change){
      input.value = change.object[attr];
    });
  }, ['update']);
Since everything in this particular Polymer element is an update, this does not have the desired effect. All changes are sent to the observer callback.

In other words, for my particular use-case, MutationObserver and Object.observe are identical—requiring identical callback handlers to update the form element. And, since MutationObserver (currently) has broader support, I will likely stick with it in the book.


Day #3

No comments:

Post a Comment