Last active
December 23, 2015 23:49
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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