Created
November 10, 2010 23:47
-
-
Save regular/671736 to your computer and use it in GitHub Desktop.
an implementation of require() that runs in a browser and downloads code from a server
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
// require.js | |
// a browser-side implementation of require() | |
// (c) 2010 Jan Bölsche <[email protected]> | |
// See my blog post at http://blog.lagomorph.de/2010/11/require-requirements | |
// This code is licenced under the terms of the GPL (any version you prefer) | |
// requires JQuery. | |
var moduleExports = {}; // hash of hashes, stores exported objects of all loaded modules | |
// loadModule() loads a module from the web server and resolve all | |
// requirements (by loading more code from the server) | |
// The exported objects of all loaded modules can be found | |
// in moduleExports. | |
// This function returns immediately and has no return value. | |
// If the operation succeeds, onLoad is called with the name of the | |
// module that was just loaded as the first argument and its exports | |
// as the second argument. onError is called with the name of the module | |
// in case the file could not be downloaded. | |
// CAVEATS | |
// TODO: catch and report errors that occur while evaluating a module's code. | |
// FIXME: modules may be loaded and evaluated more then once. | |
function loadModule(moduleName, onLoad, onError) { | |
// evaluateModule() runs downloaded code and | |
// potentially triggers the download of its dependencies. | |
// It only succeeds if all dependencies are already loaded. | |
// Otherwise it will call loadModule which in turn will | |
// call back evaluateModule() once the new code is loaded. | |
function evaluateModule(moduleName, code, onSuccess, onError) { | |
exports = {}; // will be filled by the module to be evaluated | |
// The following is the implementation of require() | |
// that is visible to downloaded modules | |
// while they are being evaluated. | |
// If the path specified refers to a module | |
// that was already loaded, the method succeeds. | |
// Otherwise it triggers the download and fails with | |
// an exception. | |
// Once the download is finished, the callback function | |
// retries to evaluate the module that originally called | |
// require(). | |
var require = function(path) { | |
if (path.substring(0, 2) == "./") { | |
path = path.substring(2); | |
} | |
if (path in moduleExports) { | |
console.log("required module " + path + " is already loaded."); | |
return moduleExports[path]; | |
} | |
console.log("required module " + path + " is not loaded yet."); | |
loadModule(path, function() { | |
evaluateModule(moduleName, code, onSuccess, onError); | |
}, onError | |
); | |
throw "required module " + path + " not yet loaded (now laoding)"; | |
} | |
// the following line might throw an | |
// excpetion due to an unresolved required module | |
// in that case we will be called again after | |
// that module has been loaded, so we just return. | |
eval(code); | |
// otherwise we get here, store the exports | |
// exposed by the new module for future use | |
// and report success. | |
moduleExports[moduleName] = exports; | |
onSuccess(); | |
return exports; | |
} | |
if (moduleName in moduleExports) { | |
if (onSuccess != undefined) { | |
onSuccess(moduleName, moduleExports[moduleName]); | |
} | |
return; | |
} | |
console.log("trying to load module " + moduleName + " ..."); | |
jQuery.ajax({ | |
dataType: 'text', | |
url: '/' + moduleName.toLowerCase() + '.js', | |
'success': function(data, textStatus, request) { | |
evaluateModule(moduleName, data, | |
function() { | |
if (onLoad != undefined) { | |
onLoad(moduleName, moduleExports[moduleName]); | |
} | |
}, | |
function() { | |
if (onError != undefined) { | |
onError(moduleName); | |
} | |
} | |
); | |
}, | |
'error': function(request, textStatus, errorThrown) { | |
console.log("failed to download module " + moduleName); | |
if (onError != undefined) { | |
onError(moduleName); | |
} | |
} | |
}); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment