Saturday, March 28, 2015

Debouncing with scheduleJob in Polymer.dart


I make these little notes for myself and then I have no idea what they mean.

While awaiting the copy edits for the latest Patterns in Polymer, I have been reviewing research tasks that I have assigned myself. I have a pretty good handle on the challenges of the <google-map> API (especially in Dart), so I have checked that off. Next on the list is “native Polymer debounce.” Since Polymer tends to have as many polyfills as it has native components, I doubt the debounce is native, but let's see...

Mercifully, Michael Bleigh was king enough to use the word “debounce” on his post about Polymer Features That You May Have Missed. And indeed, I missed that one, which is called job().

At first blush, job() seems fairly straight-forward in the JavaScript sample from the article, so I'll have a go at it in Polymer.dart. Oddly enough, I have a debounce example in Patterns in Polymer, but it is only in the Dart version of the book. Using 3rd party libraries is so easy in Dart that I wrote that chapter about using 3rd party JavaScript libraries in Polymer.dart. The example in the book is using the Underscore debounce() method:
class HelloYou extends PolymerElement {
  // ...
  HelloYou.created(): super.created();

  var _debouncedLucky;
  feelingLucky() {
    if (_debouncedLucky == null) {
      _debouncedLucky = context['_'].
        callMethod('debounce', [_feelingLucky, 750, true]);
    }
    _debouncedLucky.apply([]);
  }

  _feelingLucky() { /* ... */ }
}
The feelingLucky() method is bound to a button in the template. The private _feelingLucky() Dart method is debounced by Underscore thanks to js-interop.

If I am correct, I believe that I can replace all of that with scheduleJob():
@CustomTag('hello-you')
class HelloYou extends PolymerElement {
  HelloYou.created(): super.created();
  // ...
  PolymerJob _debouncedLucky;
  feelingLucky() {
    _debouncedLucky = scheduleJob(_debouncedLucky, _feelingLucky, 750);
  }

  _feelingLucky() { /* ... */ }
}
Of course, I am not correct. The debounce duration needs to be supplied as a Duraction, not an integer number of seconds. Dart complains as much:
Exception: Uncaught Error: Class 'int' has no instance getter 'inMilliseconds'.
To supply the required Duration, I declare a delay duration of 750 milliseconds and supply that to scheduleJob():
final delay = const Duration(milliseconds: 750);

@CustomTag('hello-you')
class HelloYou extends PolymerElement {
  HelloYou.created(): super.created();
  // ...
  PolymerJob _debouncedLucky;
  feelingLucky() {
    _debouncedLucky = scheduleJob(_debouncedLucky, _feelingLucky, delay);
  }

  _feelingLucky() { /* ... * }
}
With that, I can click the feeling lucky button as many times as I like in the UI, but, unless I wait 750 milliseconds between clicks, nothing happens. Once I wait, my simple <hello-you> element tries to guess my lucky color while saying howdy:



That is a handy little feature that I had overlooked. Well, not overlooked so much as deferred, but thankfully I can mention this by name in the book now.


Day #12

No comments:

Post a Comment