Skip to content

Instantly share code, notes, and snippets.

@ItsAsbreuk
Last active December 23, 2015 23:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ItsAsbreuk/6712217 to your computer and use it in GitHub Desktop.
Save ItsAsbreuk/6712217 to your computer and use it in GitHub Desktop.
publishAsync method at the prototype of Y.Model, which publishes events with asynchronous defaultFn and preventedFn Promises
// Special thanks to Luke Smiths !! https://github.com/lsmith, who helped me creating this custom publish-method.
// More details https://gist.github.com/lsmith/6664382/db6e9e3342d5a7610d0efc3e4b72b480604ce46a
YModel.prototype.publishAsync = function(type, opts) {
var instance = this,
asyncEvent = this.publish(type, opts);
asyncEvent._firing = new Y.Promise(function (resolve) { resolve(); });
asyncEvent.fire = function (data) {
var args = Y.Array(arguments, 0, true),
stack = {
id: asyncEvent.id,
next: asyncEvent,
silent: asyncEvent.silent,
stopped: 0,
prevented: 0,
bubbling: null,
type: asyncEvent.type,
defaultTargetOnly: asyncEvent.defaultTargetOnly
}, next;
asyncEvent._firing = asyncEvent._firing.then(function () {
asyncEvent.details = args;
// Execute on() subscribers
var subs = asyncEvent._subscribers,
args2 = [],
e, i, len;
args2.push.apply(args2, data);
e = asyncEvent._createFacade(args2);
e.target = e.target || instance;
if (subs) {
for (i = 0, len = subs.length; i < len; ++i) {
try {
subs[i].fn.call(subs[i].context, e);
}
catch (catchErr) {
Y.log("Error in defaultFn or after subscriber: " + (catchErr && (catchErr.message || catchErr)), ERROR);
}
}
}
// Execute on() subscribers for each bubble target and their respective targets:
if (asyncEvent.bubbles && !asyncEvent.stopped) {
instance.bubble(asyncEvent, args, null, stack);
e.prevented = Math.max(e.prevented, stack.prevented);
}
// Resolve the _firing promise with either prefentedFn promise if it was prevented, or with a promise for
// the result of the defaultFn followed by the execution of the after subs.
return e.prevented ?
asyncEvent.preventedFn.call(instance, e).then(null, function (reason) {
Y.log("Error in preventedFn: " + (reason && (reason.message || reason)), ERROR);
return false;
}) :
asyncEvent.defaultFn.call(instance, e).then(function () {
// no need to handle 'response' it is merged into 'e' within the defaultfunction
// Execute after() subscribers
subs = asyncEvent._afters;
if (subs) {
for (i = 0, len = subs.length; i < len; ++i) {
try {
subs[i].fn.call(subs[i].context, e);
}
catch (catchErr) {
Y.log("Error in defaultFn or after subscriber: " + (catchErr && (catchErr.message || catchErr)), ERROR);
}
}
}
// Execute after() subscribers for each bubble target and their respective targets:
if (stack.afterQueue) {
while ((next = stack.afterQueue.last())) {
next();
}
}
// Catch errors/preventions and reset the promise state to fulfilled for
// the next call to fire();
}).then(null, function (reason) {
Y.log("Error in defaultFn or after subscriber: " + (reason && (reason.message || reason)), ERROR);
return false;
});
},
function(reason) {
var facade = {
error : reason,
src : 'Model.publishAsync()'
};
Y.log("Error in publishAsync: " + (reason && (reason.message || reason)), ERROR);
instance._lazyFireErrorEvent(facade);
});
};
asyncEvent._fire = function (args) {
return asyncEvent.fire(args[0]);
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment