Я новичок в JavaScript. Я разработал один код для получения некоторых выходных URL-адресов с помощью API-интерфейса. Когда я использовал приведенный ниже код, он говорит, что функции, объявленные в цикле, ссылаются на переменную внешней области. Я понимаю, что это связано с внешней областью видимости переменной obj, но как я могу заставить ее работать. Пожалуйста, помогите. Ниже приведен код,
var obj = [
{"Id":"10101","descr":"server1.com"},
{"Id":"10102","descr":"server2.com"},
{"Id":"10103","descr":"server3.com"},
{"Id":"10104","descr":"server4.com"},
{"Id":"10105","descr":"server5.com"},
{"Id":"10106","descr":"server6.com"},
{"Id":"10107","descr":"server7.com"}
];
var temp = [];
for (var i = 0; i < obj.length; i++){
var id = obj[i].Id;
fetch('https://abced.com/api/'+id+'/value', {
method : "GET",
headers: { "Authorization": "xyz" }
})
.then(res => res.json())
.then(data => {
var stats = data.status;
if (stats != "OK") {
temp.push({ Id: obj[i].Id, descr: obj[i].descr, value:"ERROR" });
}
console.info(temp);
})
.catch(x => console.info("fail:", x))
}
Мой ожидаемый результат. (значения Id и descr будут зависеть от оператора if в коде)
[{"Id": "10101","descr": "server1.com","status": "ERROR"},
{"Id": "10103","descr": "server3.com","status": "ERROR"},
{"Id": "10104","descr": "server4.com","status": "ERROR"}]
И, пожалуйста, сделайте отступ в коде, чтобы улучшить читабельность.
Вы должны работать с асинхронностью: dmitripavlutin.com/javascript-fetch-async-await
Вы также можете прочитать об асинхронных событиях в javascript в целом: digitalocean.com/community/tutorials/…
нажмите обещание выборки, которое преобразует значение в массив обещаний, затем используйте Promise.all, чтобы сделать что-то, как только они все будут разрешены блокировать
Сообщение, вероятно, относится не к obj и tmp, а скорее к i и id. И i, и id определяются в цикле for с помощью var. Это означает, что существует одна единственная переменная i и id, которая является общей для разных итераций. К тому времени, когда вызываются обратные вызовы .then(), i уже не то же самое, а вместо этого obj.length. id будет установлен на последний id в цикле. Как правило, всегда используйте let или const. Используйте var только в том случае, если у вас есть для этого конкретная причина. Определение i и id с помощью let означает, что каждая итерация имеет свою собственную переменную.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я бы посоветовал использовать синтаксис async...await, его намного легче читать, чем множество обработчиков .then().
Мы бы использовали цикл for .. of для перебора каждого значения Id, descr в нашем массиве obj, делая соответствующий fetch() вызов для каждого из них.
Мы ждем результата каждого вызова выборки, а затем проверяем статус. Если не в порядке, добавляем в массив результатов.
var obj = [
{"Id":"10101","descr":"server1.com"},
{"Id":"10102","descr":"server2.com"},
{"Id":"10103","descr":"server3.com"},
{"Id":"10104","descr":"server4.com"},
{"Id":"10105","descr":"server5.com"},
{"Id":"10106","descr":"server6.com"},
{"Id":"10107","descr":"server7.com"}
];
async function getResults() {
const results = [];
for(let { Id, descr} of obj) {
const data = await fetch('https://abced.com/api/' + Id + '/value', {
method : "GET",
headers: { "Authorization": "xyz" }
}).then(res => res.json());
if (data.status !== 'OK') {
results.push({ Id, descr, value: 'ERROR' })
}
}
return results;
}
async function test() {
const results = await getResults();
console.info('Results:', results)
}
test();
Ниже приведен фрагмент, где я смоделировал выборку, это должно дать вам представление о том, чего ожидать.
fetchMock возвращает статус «ПЛОХО» для идентификаторов 10101, 10103, 10104 и «ОК» для всех остальных.
// For testing only, replace with fetch when appropriate...
function fetchMock(url) {
let id = url.split('/')[4];
if ([10101, 10103, 10104].includes(+id)) {
return Promise.resolve({ json() { return Promise.resolve({ status: 'BAD'})}})
} else {
return Promise.resolve({ json() { return Promise.resolve({ status: 'OK'})}})
}
}
var obj = [
{"Id":"10101","descr":"server1.com"},
{"Id":"10102","descr":"server2.com"},
{"Id":"10103","descr":"server3.com"},
{"Id":"10104","descr":"server4.com"},
{"Id":"10105","descr":"server5.com"},
{"Id":"10106","descr":"server6.com"},
{"Id":"10107","descr":"server7.com"}
];
async function getResults() {
const results = [];
for(let { Id, descr} of obj) {
const data = await fetchMock('https://abced.com/api/' + Id + '/value', {
method : "GET",
headers: { "Authorization": "xyz" }
}).then(res => res.json());
if (data.status !== 'OK') {
results.push({ Id, descr, value: 'ERROR' })
}
}
return results;
}
async function test() {
const results = await getResults();
console.info('Results:', results)
}
test().as-console-wrapper { max-height: 100% !important; }Кажется, это работает, но также возвращает ожидаемое обещание вместе с массивом Promise {<ожидание>} (3) [{…}, {…}, {…}] У меня есть еще один фрагмент кода, который содержит приведенный выше код, который возвращает только значение, вот этот фрагмент кода fetch('https://getserver.com/api').then((res) => res.json()).then(function(data) { var value = data.values; const formatData = (temp) => { return temp.map(({ Id, value: {descr}}) => ({Id, descr})); }; var output = formatData(value); console.info(output) }).catch(e => { console.info("fetch fail: " + e);});
Он вернет ожидающее обещание, если вы не ожидаете его в вызывающей функции. Вы также можете вызвать .then() для результата.
Можно ли написать весь код с обозначением «.then», потому что это работает для моей системы. (Как фрагмент, который я добавил в предыдущем комментарии)
Спасибо за предложения. Этот вопрос улажен.
К сожалению, в вашем коде довольно много основных синтаксических ошибок. Можете ли вы исправить это, пожалуйста, и отредактируйте свой вопрос соответствующим образом?