У меня проблемы с загрузкой текстового файла в строку во внешнем javascript-приложении без каких-либо внешних библиотек.
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", filename, true)
xmlhttp.send()
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4)
myvariable = xmlhttp.responseText
}
Этот код загружает текстовый файл в переменную асинхронно, но эта переменная доступна только внутри блока onreadystatechange, когда ответ в конечном итоге возвращается.
Любая попытка вывести эту переменную за пределы этой области приводит к выполнению кода перед возвратом ответа, и переменная всегда неопределена.
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
}
Некоторые люди предложили эту модель в качестве решения проблемы. Однако это представляет точно ту же проблему, что фактически решает проблему в большинстве сценариев, где это предлагается,
async: false
Я стараюсь абстрагироваться от процесса загрузки файла, так как он будет происходить несколько раз в моем коде и, возможно, будет пересмотрен несколько раз Я хочу, чтобы загрузка всего файла была абстрагирована в одну функцию, которую я могу вызывать в любом месте моего кода, не беспокоясь о вложении моего кода в обратные вызовы алгоритмически неважных задач ввода-вывода. Я также стараюсь избегать использования только синхронного запроса. Но, прочитав другие решения, я не уверен, возможно ли это.
Я пытаюсь сделать это в чистом JavaScript без каких-либо внешних библиотек.
РЕДАКТИРОВАТЬ 1/5/18
Попытавшись реализовать это с помощью async / await и Promises, я остался в очень похожей ситуации.
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
}
Вызов функции loadFile () возвращает обещание, которое разрешается до значения myfile. Однако, чтобы получить это значение, нам нужно позвонить
loadFile().then(myfile => { /* Use my varible here */})
Это оставляет меня в точно такой же ситуации, когда остальная часть моего кода должна быть обернута в функции, созданные неважными вызовами ввода-вывода. Странная вещь в этом заключается в том, что внутри функции loadFile (), которая объявлена как асинхронная, если я использую ключевое слово await, код ведет себя синхронно, то есть поведение, которое я пытаюсь получить в остальной части моего кода.
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*/
}
Синтаксис async / await, по-видимому, не дает никаких преимуществ по сравнению с использованием прямого обещания, мне все равно пришлось вручную создавать обещание, и я, похоже, распаковываю и перепаковываю полученное значение прямо в другое обещание.
Я что-то здесь упускаю?