I'm having trouble loading a text file into a string in a front end javascript application without any external libraries.
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", filename, true)
xmlhttp.send()
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4)
myvariable = xmlhttp.responseText
}
This code loads the text file into a variable asyncronously, but the variable is only avaliable inside the onreadystatechange block when the response is eventually returned. Any attempt to get this variable outside this scope results in the code being executed before the response is returned and the variable is always undefined.
function getFile(filename, callback) {
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", filename, true)
xmlhttp.send()
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4)
callback(xmlhttp.responseText)
}
}
function loadFile(filename) {
var myString
getFile(filename, function(reponseText){
myString = responseText
})
return myString
}
Some people have proposed this pattern as a solution to the problem. However this presents exacly the same problem, what is acctualy solving the problem in most scenarios where this is proposed is
async: false
I'm tring to abstract away the file loading process as it will happen multiple times in my code and possibly be revised several times. I want the entire file loading to be abstracted into a single funciton that I can call anywhere in my code without having to worry about nesting my code inside the callbacks of algorithmically unimportant IO tasks. I'm also trying to avoid just using a sycronous request. But having read other solutions, I'm not sure if this is possible.
I'm trying to do this in pure javascript without any external libraries.
EDIT 1/5/18
Having tried implementing this with async/await and Promises I'm left with a very similar situation.
function getFile(filename) {
return new Promise(function(resolve, reject){
xmlhttp = new XMLHttpRequest()
xmlhttp.open("GET", filename, true)
xmlhttp.overrideMimeType("text/plain")
xmlhttp.send()
xmlhttp.onload = function() {
if (xmlhttp.status == 200) {
resolve(xmlhttp.responseText)
}
else {
reject()
}
}
})
}
async function loadFile(filename) {
myfile = await getFile(filename)
return myfile
}
Calling the loadFile() function returns a promise that resolves to the value of myfile. However to get that value we need to call
loadFile().then(myfile => { /* Use my varible here */})
This leaves me in exactly the same situation where the rest of my code needs to be wrapped in functions created by unimportant IO calls. The strange thing about this is that inside the loadFile() function that is declared async, if i use the the await keyword the code behaves syncronously, which is the behavior im trying to get in the rest of my code.
async function loadFile(filename) {
myfile = await getFile(filename)
/* myfile is set here, like in syncronous code*/
return myfile
/* This returns a promise, getting us back to square 1*/
}
The async/await syntax doesnt appear to offer any advantage over using a straight up promise, I've had to manually construct a promise anyway and I appear to be unpacking and repackaging the resulting value straight into another promise.
Am I missing something here?