предупреждение вы получаете, потому что синхронные XMLHttpRequest, как правило, не рекомендуется: он может повесить браузер, если сервер не отвечает сразу.
Если вы только собираетесь запустить это на localhost
, вы можете игнорировать предупреждение, если хотите, или, лучше, изменить синхронный запрос на асинхронный.
Что делает его синхронным является третьим параметром для .open()
вызова:
rawFile.open("GET", file, false);
Чтобы сделать это асинхронно, изменить что верно:
rawFile.open("GET", file, true);
Или просто опустить параметр, потому что true
является по умолчанию:
rawFile.open("GET", file);
Остальные y наш код должен работать так, как есть. (Он работал для меня в кратчайшие сроки.) Вы уже написали код таким образом, который будет работать с асинхронным запросом: вы используете данные в обратном вызове , когда readyState === 4
, вместо того, чтобы предполагать, что он будет доступен сразу после того, как вы произнесете вызов .open()
, как это может сделать синхронный код.
Для получения дополнительной информации см. MDN documentation.
Update 1
Проблема с rules
быть определено вне onreadystatechange
обратного вызова является нормальным, ожидаемое поведение. Помните, что мы теперь изменили запрос на асинхронный.То есть, вызов .open()
инициирует запрос, а затем возвращает сразу, прежде чем данные будут возвращены сервером (даже сервер на localhost
).
Решение этого просто: не пытайтесь получить доступ к встроенным данным после запроса. Вместо этого вы можете получить доступ только от в пределах функции обратного вызова успеха или от другой функции, которую вы вызываете из этого обратного вызова.
Например, в обновленном коде просто переместите вызов console.log()
в конец обратного вызова, как показано ниже, или позвоните по другой функции, если хотите. Что бы вы ни делали с данными, следуйте этой схеме.
Кроме того, не объявляйте rules
в верхней части кода; это приведет только к путанице, потому что значение rules
недоступно до тех пор, пока не будет вызвана функция обратного вызова успеха (как вы обнаружили). Вместо этого объявите его внутри обратного вызова.
Аналогично, left
, right1
, right2
и probability
используются только внутри forEach()
обратного вызова, так что это, где они должны быть объявлены.
Update 2
Как мы уже говорили в комментариях, регулярные выражения могут быть отличным способом, чтобы сделать этот вид строки синтаксического анализа.
Вот пример, который иллюстрирует как рабочую версию исходного кода, так и новую версию, которая использует регулярные выражения для синтаксического анализа правил.
rules.txt
файл я тестировал с выглядит следующим образом:
A -> D C : 0.00688
A -> G F : 0.43257
B -> with : 0.1875
C -> with : 0.2
Код JavaScript является:
function readRules(file) {
var request = new XMLHttpRequest();
request.open('GET', file);
request.onreadystatechange = function() {
if(request.readyState === 4) {
if(request.status === 200 || request.status == 0) {
processRules1(request.responseText);
processRules2(request.responseText);
}
}
}
request.send(null);
}
function processRules1(allText) {
var rules = {};
allText = allText.split("\n");
allText = allText.splice(0, allText.length-1);
allText.forEach(function (rule) {
left = rule[0];
probability = parseFloat(rule.slice(rule.indexOf(":")+2));
rules[left] ? rules[left] : rules[left] = {}; // init left
if (rule[6] == " ") {
right1 = rule[5];
right2 = rule[7];
rules[left][right1] ? rules[left][right1] : rules[left][right1] = {}; // init right1
rules[left][right1][right2] = probability;
} else {
right1 = rule.slice(5, rule.indexOf(":") - 1);
rules[left][right1] = probability;
}
});
console.log(JSON.stringify(rules, null, 4));
}
function processRules2(rulesText) {
var reRule = /^(\w) -> (\w+)((\w))? : ([\d.]+)$/gm;
var rules = {};
rulesText.replace(reRule, function(
line, left, right1, dummy1, right2, probability
) {
if(! rules[left]) rules[left] = {};
if(right2) {
if(! rules[left][right1]) rules[left][right1] = {};
rules[left][right1][right2] = probability;
} else {
rules[left][right1] = probability;
}
});
console.log(JSON.stringify(rules, null, 4));
}
readRules('rules.txt');
processRules1()
использует оригинальную технику, и processRules2()
использует регулярное выражение.
Обе версии журнал один и тот же результат для испытания rules.txt
файла:
{
"A": {
"D": {
"C": 0.00688
},
"G": {
"F": 0.43257
}
},
"B": {
"with": 0.1875
},
"C": {
"with": 0.2
}
}
Одна часть функции processRules2()
, что может показаться немного пугающим является само регулярное выражение:
var reRule = /^(\w) -> (\w+)((\w))? : ([\d.]+)$/gm;
Скорее чем объяснить это здесь подробно, позвольте мне указать на a page on regex101.com, который проверяет регулярное выражение и объясняет, как он работает. Дайте мне крик, если что-нибудь в их объяснении не ясно.
Кроме того, что это немного короче, регулярное выражение делает код более гибким. Например, предположим, что файл правил иногда использовал более одного пробела между значениями вместо одного пробела в вашем существующем файле. При первоначальном подходе вам придется пересчитать все смещения символов и включить код для обработки как одного пробела, так и нескольких пробелов. С регулярным выражением было бы так же просто, как изменить
(который соответствует одному пространству) до +
(который соответствует одному или более пробелам).
Также обратите внимание, что регулярное выражение позаботится о разделении файла правил на строки и игнорирует пустую строку в конце файла (вместо того, чтобы использовать .splice()
для удаления последней строки). Пустая строка просто не соответствует регулярному выражению, поэтому она игнорируется таким образом.
Нечетная вещь в коде - использование метода .replace()
. Обычно этот метод используется, когда вы действительно хотите заменить символы в строке чем-то другим. Но здесь мы просто используем его как способ для вызывать функцию для каждого совпадения в строке, а затем игнорируем значение, возвращаемое .replace()
.
И последнее предложение: В нескольких местах исходный код что-то вроде этого:
rules[left] ? rules[left] : rules[left] = {};
Условный оператор может быть удобен для аналогичных видов применения, где вы на самом деле присваивающих результат к чему-то , но в данном случае проще и понятнее использовать обычный if
заявление:
if(! rules[left]) rules[left] = {};
Можете ли вы поделиться код, который вы пробовали? Это поможет нам в предоставлении решения/предложения. –
И какие ошибки вы получали? –
Возможный дубликат [HTTP GET запрос в JavaScript?] (Http://stackoverflow.com/questions/247483/http-get-request-in-javascript) – Jonathan