Created
September 26, 2017 20:12
-
-
Save bhauman/8af183a13e4446d45bdfe2b285a976df to your computer and use it in GitHub Desktop.
Loading a ClojureScript/Figwheel project with fetch instead of writing script tags.
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
/* | |
* This script provides an example of loading a ClojureScript project | |
* that has been compiled using optimizations level :none. | |
* | |
* There are many environments that might not support the default | |
* method of writing script tags to load files. | |
* | |
* I wrote this to solve the problem of loading compiled ClojureScript | |
* into Chrome extentions. | |
* | |
* The key here is that you have to handle asynchronous nature of | |
* loading files via 'fetch' or 'xmlhttprequest' while using the synchronous | |
* loading style of goog.base to request all the dependencies in the | |
* correct order. | |
* | |
* Usage: | |
* You will need the ClojureScript base path. I.E. the path to base.js | |
* Load a namespace: | |
* | |
* ClojureScriptLoader("http://localhost:3449/js/compiled/out/goog/") | |
* .loadNamespace("example.core") | |
* .then(function(v){consoel.log("Namspace loaded")}) | |
* | |
* Load a figwheel build: | |
* | |
* ClojureScriptLoader("http://localhost:3449/js/compiled/out/goog/") | |
* .loadFigwheelBuild("dev") | |
* .then(function(v){consoel.log("figwheel build loaded")}) | |
* | |
*/ | |
ClojureScriptLoader = function(googBasePath){ | |
var evaluate = eval; | |
var debug = false; | |
var asyncImportChain = Promise.resolve(true); | |
function logDebug(s) { | |
if(debug) { | |
console.log(s); | |
} | |
} | |
function asyncImportScripts(url, success, error) { | |
logDebug('Importing: ' + url); | |
// TODO success and error not needed | |
var noop = function(){}; | |
success = (typeof success == 'function') ? success : noop; | |
error = (typeof error == 'function') ? error : noop; | |
asyncImportChain = | |
asyncImportChain | |
.then(function (v) {return fetch(url);}) | |
.then(function (response) { | |
if(response.ok) | |
return response.text(); | |
throw new Error("Failed to Fetch: " + url) | |
}) | |
.then(function (responseText) { | |
console.log("Evaluating: " + url); | |
evaluate(responseText); | |
success(); | |
return true; | |
}) | |
.catch(function (e) { | |
console.error(e); | |
error(); | |
return true; | |
}); | |
} | |
function importJs(url, opt_sourceText) { | |
if(opt_sourceText === undefined) { | |
asyncImportScripts(url); | |
} else { | |
evaluate(opt_sourceText); | |
} | |
} | |
function figwheelImportScript(uri, callback) { | |
asyncImportScripts(uri.toString(), | |
function () {callback(true);}, | |
function () {callback(false);}) | |
} | |
function bootstrapGoogBase(googBasePath) { | |
importJs(googBasePath + "base.js"); | |
asyncImportChain = asyncImportChain.then(function(v) { | |
goog.basePath = googBasePath; | |
goog.global.CLOSURE_IMPORT_SCRIPT = importJs; | |
goog.global.FIGWHEEL_IMPORT_SCRIPT = figwheelImportScript; | |
}); | |
importJs(googBasePath + "../cljs_deps.js"); | |
importJs(googBasePath + "deps.js"); | |
} | |
function pollFor(pred,callback) { | |
setTimeout(function() { | |
if(pred()) { | |
callback(); | |
} else { | |
pollFor(pred,callback); | |
} | |
}, 500); | |
} | |
function googRequireNamespace(mainNamespace) { | |
var loaded = false; | |
asyncImportChain = | |
asyncImportChain.then(function(v) { | |
goog.require(mainNamespace); | |
// the above call is synchronous so all | |
// the import promises have been chained at this point | |
// so hang a listener off of the last one to test when everything | |
// is loaded | |
asyncImportChain.then(function(v) { | |
loaded = true; | |
}); | |
}); | |
return new Promise(function(res,rej){ | |
pollFor(function(){return loaded;}, | |
function(){res(mainNamespace)}); | |
}); | |
} | |
function loadClojureScriptNamespace(googBasePath, namespace){ | |
bootstrapGoogBase(googBasePath); | |
return googRequireNamespace(namespace); | |
} | |
return {loadNamespace: function(namespace) { | |
return loadClojureScriptNamespace(googBasePath, namespace); | |
}, | |
loadFigwheelBuild: function(build_id) { | |
return loadClojureScriptNamespace(googBasePath, | |
"figwheel.connect.build_" + build_id); | |
}} | |
} | |
/* | |
function testIt() { | |
ClojureScriptLoader("http://localhost:3449/js/compiled/out/goog/") | |
.loadFigwheelBuild("dev") | |
.then(function(){console.log("Loaded figwheel")}); | |
} | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment