My latest challenge involves writing client-side javascript that can perform several tasks asynchronously:
- Retrieve a text file from the server and send the response to a callback function
- Utilize the callback function to parse the response into an array
- Store that array in a constant within the global scope
The reason for wanting the response data stored as a constant globally is so I can easily access the array by clicking on the UI without having to repeatedly send the same HTTP request with each click. However, after attempting this for a few days, I'm beginning to think that step 3 may be unachievable. Here is the code snippet I am using to handle sending the http request and processing the response.
"use strict"
// getText sends an HTTP GET request to a specified URL and then
// passes the received text response to a callback function for parsing.
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)
}
This next section of the code shows how the text is parsed and assigned to a global variable. While it currently functions correctly, there exists a potential issue:
let wordBank
function textParserCallback(text) {
wordBank = text
.split("\r\n")
.filter((string)=>{
if (string.length > 0) return string
})
}
getText("textFile.txt", textParserCallback)
Any function has the ability to assign values to wordBank, even though wordBank will never require any changes or updates. This is poor design and could lead to bugs. My attempt to address this involved organizing 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 fires before textParserCallback completes
return wordBank
}
const globalWordBank = myModule() // undefined
Unfortunately, the return statement executes prematurely.
I have reviewed How do I return the response from an asynchronous call? and other related queries which were resolved by handling the response immediately following the corresponding request. However, as mentioned earlier, I wish to avoid making repeated requests for the same unchanging data whenever I need to update the UI. Additionally, consolidating all my text parsing, DOM listening, and UI updating code into one lengthy callback makes the code difficult to read and debug. The function name "getText" no longer adequately describes its functionality.
If solving this challenge proves impossible, I could always compile the text file into an array and manually insert it into my program. Yet, a part of me fears encountering a similar problem in the future, albeit in a different context where the data size exceeds what can be stored in the program. Hence, I am reaching out here in hopes of finding a solution or verifying whether my current objective is indeed unattainable.