I've been trying to write some client-side javscript which does the following things asynchronously:
- Request a text file from the server and pass the response to a callback
- Use said callback function to parse the response into an array
- Assign that array to a constant in the global scope
I want to assign the response data to a constant in the global scope because it will allow me to access the array by clicking on the UI without sending the same HTTP request on every click. It's been a few days now and I'm starting to think that step 3 is impossible. Here is the function I'm using to send an http request and handle the response.
"use strict"
// getText will send an HTTP GET request to a given URL, and then
// pass the response text to a callback function so it can be parsed.
function getText(url, callBack) {
const rawFile = new XMLHttpRequest()
rawFile.open("GET", url)
rawFile.onreadystatechange = ()=>{
if (rawFile.readyState === 4) {
if (rawFile.status === 200 || rawFile.status === 0) {
callBack(rawFile.responseText)
}
}
}
rawFile.send(null)
}
And here is the part of the code where the text is parsed, and then assigned to a global variable. It does work, but it has a problem:
let wordBank
function textParserCallback(text) {
wordBank = text
.split("\r\n")
.filter((string)=>{
if (string.length > 0) return string
})
}
getText("textFile.txt", textParserCallback)
Any function can assign values to wordBank, despite the fact that wordBank will never need to be changed or updated. This is bad design and will most certainly lead to bugs. I attempted to solve the problem by placing the response handler logic into a revealing module:
function myModule() {
let wordBank
function textParserCallback(text) {
wordBank = text
.split("\r\n")
.filter((string)=>{
if (string.length > 0) return string
})
}
getText("textFile.txt", textParserCallback)
// the return statement will fire before textParserCallback is finished
return wordBank
}
const globalWordBank = myModule() // undefined
But the return statement fires too early.
I've read How do I return the response from an asynchronous call? and various other questions which were solved by simply handling the response directly after the corresponding request, however as I stated above, I do not want to keep requesting the same, immutable data every time I need to update the UI. Another issue with that approach is that putting all of my text parsing, DOM listening, and UI updating code into one long callback makes my code really hard to read and debug. "getText" would no longer adequately describe what was going on.
If this does turn out to be impossible, I can always just compile the text file into an array and copy paste that into my program. Still, part of me worries that one day, I'll encounter this problem again, in a different form, and on that day the data will be too large to store in the program. With that in mind, I'm posting this here, hoping to find a solution, or proof that what I am attempting is indeed impossible.