Created
October 6, 2012 18:45
-
-
Save solmsted/3845763 to your computer and use it in GitHub Desktop.
yui-soon
This file contains hidden or 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
/** | |
* Provides a setImmediate/setTimeout wrapper. This module is a `core` YUI | |
* module, <a href="../classes/YUI.html#method_soon">its documentation is | |
* located under the YUI class</a>. | |
* | |
* @module yui | |
* @submodule yui-soon | |
* @author Steven Olmsted | |
*/ | |
var subscribedToMessageEvent, | |
/** | |
* Y.soon accepts a callback function. The callback function will be | |
* called once in a future turn of the JavaScript event loop. If the | |
* function requires a specific execution context or arguments, wrap it | |
* with Y.bind. Y.soon returns an object with a cancel method. If the | |
* cancel method is called before the callback function, the callback | |
* function won't be called. | |
* @method soon | |
* @for YUI | |
* @param {Function} callbackFunction | |
* @return {Object} | |
* @param {Function} cancel If the cancel method is called before the | |
* callback function, the callback function won't be called. | |
*/ | |
soon = function (callbackFunction) { | |
var canceled; | |
soon._asynchronizer(function () { | |
// Some asynchronizers may provide their own cancellation methods | |
// such as clearImmediate or clearTimeout but some asynchronizers | |
// do not. For simplicity, cancellation is entirely handled here | |
// rather than wrapping the other methods. All asynchronizers are | |
// expected to always call this anonymous function. | |
if (!canceled) { | |
callbackFunction(); | |
} | |
}, 0); | |
// The 0 is required when setTimeout is used, but it should be ignored | |
// by other asynchronizers. | |
return { | |
cancel: function () { | |
canceled = 1; | |
} | |
}; | |
}; | |
/** | |
* The asynchronizer is the internal mechanism which will call a function | |
* asynchronously. This property is exposed as a convenient way to define a | |
* different asynchronizer implementation without having to rewrite the entire | |
* Y.soon interface. | |
* @method _asynchronizer | |
* @for soon | |
* @param {Function} callbackFunction The function to call asynchronously. | |
* @protected | |
*/ | |
/** | |
* Since Y.soon is likely to have many differing asynchronizer implementations, | |
* this property should be set to identify which implementation is in use. | |
* @property _impl | |
* @protected | |
* @type String | |
*/ | |
// Check for a native or already polyfilled implementation of setImmediate. | |
if ('setImmediate' in Y.config.win) { | |
soon._asynchronizer = Y.config.win.setImmediate; | |
soon._impl = 'setImmediate'; | |
} else if ('mozSetImmediate' in Y.config.win) { | |
soon._asynchronizer = Y.config.win.mozSetImmediate; | |
soon._impl = 'mozSetImmediate'; | |
} else if ('msSetImmediate' in Y.config.win) { | |
soon._asynchronizer = Y.config.win.msSetImmediate; | |
soon._impl = 'msSetImmediate'; | |
} else if ('oSetImmediate' in Y.config.win) { | |
soon._asynchronizer = Y.config.win.oSetImmediate; | |
soon._impl = 'oSetImmediate'; | |
} else if ('webkitSetImmediate' in Y.config.win) { | |
soon._asynchronizer = Y.config.win.webkitSetImmediate; | |
soon._impl = 'webkitSetImmediate'; | |
} | |
// Check for postMessage but make sure we're not in a WebWorker. | |
else if (('postMessage' in Y.config.win) && !('importScripts' in Y.config.win)) { | |
soon._asynchronizer = function (callbackFunction) { | |
if (!subscribedToMessageEvent) { | |
// Subscribe to the message event. | |
YUI.Env.add(Y.config.win, 'message', function (event) { | |
// Only pay attention to messages from this window. | |
if (event.source === Y.config.win) { | |
// The message we've received in event.data could be | |
// anything. If it's a Y.soon message id, there will be a | |
// callback function associated with it. | |
var id = event.data, | |
callbackFunction = soon._asynchronizer[id]; | |
if (callbackFunction) { | |
// There is a callback function, so call it. | |
callbackFunction(); | |
// We no longer need to keep the callback function. | |
delete soon._asynchronizer[id]; | |
// Other listeners should't care about this message. | |
if (event.stopImmediatePropagation) { | |
event.stopImmediatePropagation(); | |
} else { | |
event.stopPropagation(); | |
} | |
event.preventDefault(); | |
} | |
} | |
}, false); | |
subscribedToMessageEvent = true; | |
} | |
// Create a unique Y.soon message id for this callback function. | |
var id = Y.guid('soon'); | |
// Store the callback function to be called later by the event handler. | |
soon._asynchronizer[id] = callbackFunction; | |
// Send the message, but make sure it does not get sent to listeners | |
// from another origin. | |
Y.config.win.postMessage(id, Y.config.win.location); | |
}; | |
soon._impl = 'postMessage'; | |
} | |
// The most widely supported asynchronizer is setTimeout so we use that as the | |
// fallback. | |
else { | |
soon._asynchronizer = setTimeout; | |
soon._impl = 'setTimeout'; | |
} | |
Y.soon = soon; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment