Question

I am trying implement async event leveraging YUI3 library. So the application had been notified about event passed even with late subscription, simular like load or ready events do.

Here it is what I have so far, but no luck around.

YUI().use('event', 'event-custom', function(Y){

  function onCustomEvent () {
    Y.Global.on('custom:event', function(){
      alert('custom fired');
    });
  }
  window.setTimeout(onCustomEvent, 2000);
});

YUI().use('event', 'event-custom', function(Y){

  Y.publish('custom:event', {
    emitFacade: true,
    broadcast: 2,
    fireOnce: true,
    async: true
  });

  function fireCustomEvent () {
    Y.Global.fire('custom:event');
  }
  window.setTimeout(fireCustomEvent, 1000);
});

If anyone could give a hint what's wrong with this code? Thank you.

UPD:

After a bit investigations it turns out that async events work fine inside one use() instance and when not using Global broadcasting. So that's something either bug or limitation. Still discovering

Was it helpful?

Solution

Okay, at the high level the inconsistency with global events (how I understood it) lays in the sandbox nature of Y object. So at some point you could fire only sync events globally cause async parameters you subscribe to custom event made on Y instance and not passed further (and than YUI uses some defaults or whatever). This possibly makes sense but than why such kind of events should be fireable globally? Either I miss some substantial part of YUI and this is candidate for bug report.

Anyway I do not have time to dive deeper in YUI and what I really practically need could be wrapped in 40 lines of code:

YUI.add('async-pubsub', function(Y) {
  var subscribers = {};

  if ( !YUI.asyncPubSub ) {
    YUI.namespace('asyncPubSub');
    YUI.asyncPubSub = (function(){
      var eventsFired = {};
      function doPublishFor(name) {
        var subscriber;

        for ( subscriber in subscribers ) {
          if ( subscriber === name ) {
            (subscribers[name]).call();
            delete ( subscribers[name] ); // Keep Planet clean
          }  
        }
      }
      return {
        'publish': function(name, options) {
          eventsFired[name] = options || {};
          doPublishFor(name);
        },
        'subscribe': function(name, callback) {
          if ( subscribers[name] ) {
            Y.log('More than one async subscriber per instance, overriding it.', 'warning', 'async-pubsub');
          }
          subscribers[name] = callback || function() {};
          if ( eventsFired[name] ) {
            window.setTimeout(
              function () {
                doPublishFor(name);
              },0
            );
          }
        }
      };  
    })();
  }
  Y.asyncPubSub = YUI.asyncPubSub;
}, '1.0', {requires: []});

There is some limitation and room for optimization here, like ability subscribe only one action for one event per use instance, but I do not need more. I will also try to debug and enhance this snippet in future if there will be interest.

Still curious about YUI behavior, is it bug or something?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top