зеркало из https://github.com/mozilla/snowl.git
import updated Sync module
--HG-- extra : rebase_source : d25ee944d1af53b5f59043dfcb978719864503a2
This commit is contained in:
Родитель
d8210f7113
Коммит
a2965517db
140
modules/Sync.js
140
modules/Sync.js
|
@ -43,25 +43,63 @@ const Ci = Components.interfaces;
|
||||||
const Cr = Components.results;
|
const Cr = Components.results;
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
|
|
||||||
function sync(/*, arg1, arg2, ... */) {
|
/**
|
||||||
/* Grab the current thread so we can make it give up priority */
|
* Make a synchronous version of the function object that will be called with
|
||||||
var thread = Cc["@mozilla.org/thread-manager;1"].getService().currentThread;
|
* the provided thisArg.
|
||||||
|
*
|
||||||
|
* @param this {Function}
|
||||||
|
* The asynchronous function to make a synchronous function
|
||||||
|
* @param thisArg {Object} [optional]
|
||||||
|
* The object that the function accesses with "this"
|
||||||
|
* @usage let syncFunc = syncBind.call(asyncFunc, thisArg);
|
||||||
|
*/
|
||||||
|
function syncBind(thisArg) {
|
||||||
|
// Save for which function we're creating a sync version
|
||||||
|
let func = this;
|
||||||
|
|
||||||
/* Call the function with our callback and the original args */
|
// Hold the value passed in from the callback to return
|
||||||
var retval;
|
let retval;
|
||||||
this.apply(null, [function(data) {
|
|
||||||
|
// Track if the onComplete has been called
|
||||||
|
let gotComplete = false;
|
||||||
|
let onComplete = function(data) {
|
||||||
retval = data;
|
retval = data;
|
||||||
|
gotComplete = true;
|
||||||
|
};
|
||||||
|
|
||||||
/* Signal that we got the return value */
|
// Determine if the custom callback should be passed in as the first arg
|
||||||
thread = null;
|
let insertCallback = true;
|
||||||
}].concat(Array.slice(arguments)));
|
|
||||||
|
|
||||||
/* Keep waiting until our callback is triggered */
|
let syncFunc = function(/* arg1, arg2, ... */) {
|
||||||
while (thread != null)
|
// Grab the current thread so we can make it give up priority
|
||||||
thread.processNextEvent(true);
|
let thread = Cc["@mozilla.org/thread-manager;1"].getService().currentThread;
|
||||||
|
|
||||||
/* Return the value passed to the callback */
|
// Save the original arguments into an array
|
||||||
return retval;
|
let args = Array.slice(arguments);
|
||||||
|
|
||||||
|
// Inject our custom callback as the first argument for the async function
|
||||||
|
if (insertCallback)
|
||||||
|
args.unshift(onComplete);
|
||||||
|
|
||||||
|
// Call the async function bound to thisArg with the passed args
|
||||||
|
func.apply(thisArg, args);
|
||||||
|
|
||||||
|
// Keep waiting until our callback is triggered
|
||||||
|
while (!gotComplete)
|
||||||
|
thread.processNextEvent(true);
|
||||||
|
|
||||||
|
// Return the value passed to the callback
|
||||||
|
return retval;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Grabbing the onComplete converts the sync. function to not assume the first
|
||||||
|
// argument is our custom callback
|
||||||
|
syncFunc.__defineGetter__("onComplete", function() {
|
||||||
|
insertCallback = false;
|
||||||
|
return onComplete;
|
||||||
|
});
|
||||||
|
|
||||||
|
return syncFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,34 +130,50 @@ function sleep(callback, milliseconds) {
|
||||||
setTimeout(callback, milliseconds);
|
setTimeout(callback, milliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
Function.prototype.sync = sync;
|
/**
|
||||||
|
* Prepare the Function object to make synchronous functions
|
||||||
|
*
|
||||||
|
* @usage Cu.import(".../Sync.js"); Sync(Function);
|
||||||
|
*/
|
||||||
|
let Sync = function Sync(Function) {
|
||||||
|
// Basic case with undefined/global for thisArg for the synchronous function
|
||||||
|
// @usage let ret = ignoreThisFunc.sync(arg1, arg2);
|
||||||
|
// @usage let func = ignoreThisFunc.sync; let ret = func(arg1, arg2);
|
||||||
|
Function.prototype.__defineGetter__("sync", syncBind);
|
||||||
|
|
||||||
let Sync = {
|
// Allow binding of an arbitrary thisArg for the synchronous function
|
||||||
/**
|
// @usage let ret = obj.asyncFunc.syncBind(obj)(arg1, arg2);
|
||||||
* Call an asynchronous function as if it were synchronous, not returning
|
// @usage let func = obj.asyncFunc.syncBind(obj); let ret = func(arg1, arg2);
|
||||||
* until the asynchronous function completes (but without halting the thread
|
Function.prototype.syncBind = syncBind;
|
||||||
* in the meantime). Attach this to the Function prototype.
|
|
||||||
*
|
|
||||||
* Function.prototype.sync = Sync.sync;
|
|
||||||
*
|
|
||||||
* FIXME: insert usage example here.
|
|
||||||
*/
|
|
||||||
sync: sync,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sleep the specified number of milliseconds, pausing execution of the caller
|
|
||||||
* without halting the current thread.
|
|
||||||
* For example, the following code pauses 1000ms between dumps:
|
|
||||||
*
|
|
||||||
* dump("Wait for it...\n");
|
|
||||||
* Sync.sleep(1000);
|
|
||||||
* dump("Wait for it...\n");
|
|
||||||
* Sync.sleep(1000);
|
|
||||||
* dump("What are you waiting for?!\n");
|
|
||||||
*
|
|
||||||
* @param milliseconds {Number} the number of milliseconds to sleep
|
|
||||||
*/
|
|
||||||
sleep: function Sync_sleep(milliseconds) {
|
|
||||||
sleep.sync(milliseconds);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a synchronous version of the provided function, optionally binding a
|
||||||
|
* "this" for the sync function.
|
||||||
|
*
|
||||||
|
* @param func {Function}
|
||||||
|
* Async function that takes an onComplete callback as its first arg
|
||||||
|
* @param thisArg {Object} [optional]
|
||||||
|
* The object that the function accesses with "this"
|
||||||
|
* @usage let ret = Sync.sync(ignoreThisFunc)(arg1, arg2);
|
||||||
|
*/
|
||||||
|
Sync.sync = function Sync_sync(func, thisArg) syncBind.call(func, thisArg);
|
||||||
|
|
||||||
|
// Make functions in this module be sync-able (Sync.sync does something else)
|
||||||
|
Sync(Function);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sleep the specified number of milliseconds, pausing execution of the caller
|
||||||
|
* without halting the current thread.
|
||||||
|
* For example, the following code pauses 1000ms between dumps:
|
||||||
|
*
|
||||||
|
* dump("Wait for it...\n");
|
||||||
|
* Sync.sleep(1000);
|
||||||
|
* dump("Wait for it...\n");
|
||||||
|
* Sync.sleep(1000);
|
||||||
|
* dump("What are you waiting for?!\n");
|
||||||
|
*
|
||||||
|
* @param milliseconds {Number}
|
||||||
|
* The number of milliseconds to sleep
|
||||||
|
*/
|
||||||
|
Sync.sleep = sleep.sync;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче