Я пытаюсь запросить данные JSON из двух разных URL-адресов, используя fetch и отформатировать его с помощью JSX перед загрузкой в объект состояния. Он извлекает данные только из одного из URL-адресов.fetch wierdness with for ... in
У меня есть URL, в объекте, как это:
var urls = {
'recent': 'https://fcctop100.herokuapp.com/api/fccusers/top/recent',
'alltime': 'https://fcctop100.herokuapp.com/api/fccusers/top/alltime',
};
Я хочу получать данные итерируя над объектом, содержащим URL, включите его в массив объектов JSX, а затем сохранить результат в состояние моего основного объекта.
for (var key in urls) {
var url = urls[key];
fetch(url).then((response) => {
response.json().then((json) => {
var userNumber = 0;
var html = json.map((user) => {
return (
<tr>
<td>{++userNumber}</td>
<td>
<img src={user.img} alt={user.username} />
{user.username}
</td>
<td>{user.recent}</td>
<td>{user.alltime}</td>
</tr>
);
}); // Close json.map block.
this.setState({
'data': { [key]: html }
});
console.log(key);
}); // Close response.json block.
}); // Close fetch block.
}
Он должен получать данные из recent
URL и сохранить форматированный результат в this.state.data.recent
. Затем он должен сделать то же самое для alltime
, сохранив результат в this.state.data.alltime
. То, что на самом деле кажется, это сделать: alltime
дважды.
Это не имеет никакого смысла для меня вообще. Я даже не догадываюсь о том, что происходит.
Я заметил, что если я ставлю заявление войти в выборку Стреле функции она показывает, что удар оба ключа и оба адреса, но если я ставлю войти заявления в конце функции в response.json()
стрелки, после json.map
, он показывает alltime
дважды ,
Он обрабатывает второй URL дважды. Я знаю, что порядок не гарантирован, но он имеет тенденцию обрабатывать их в том порядке, в котором я их определял, и я думаю, что это важно здесь. Даже если это проблема с одновременным асинхронным запросом, они представляют собой два разных запроса, которые в конечном счете хранят данные в двух разных местах, не так ли?
Версия этого кода также является at CodePen, но я, вероятно, изменю это, поскольку я пытаюсь выяснить, что здесь происходит.
Полный код:
var urls = {
'recent': 'https://fcctop100.herokuapp.com/api/fccusers/top/recent',
'alltime': 'https://fcctop100.herokuapp.com/api/fccusers/top/alltime',
};
function View(props) {
return (
<form className="view">
<label>View: </label>
<label><input type="radio" name="view" value="recent" checked={props.view == 'recent'} />Past 30 Days</label>
<label><input type="radio" name="view" value="alltime" checked={props.view == 'alltime'} />All Time</label>
</form>
);
}
class Main extends React.Component {
constructor() {
super();
this.state = {
'view': 'recent',
'data': {
'recent': null,
'alltime': null,
},
};
}
componentWillMount() {
for (var key in urls) {
var url = urls[key];
console.log(key);
console.log(url);
fetch(url).then((response) => {
response.json().then((json) => {
var userNumber = 0;
var html = json.map((user) => {
return (
<tr>
<td>{++userNumber}</td>
<td>
<img src={user.img} alt={user.username} />
{user.username}
</td>
<td>{user.recent}</td>
<td>{user.alltime}</td>
</tr>
);
}); // Close json.map block.
console.log('Setting state for ' + key);
this.setState({
'data': { [key]: html }
});
}); // Close response.json block.
}); // Close fetch block.
}
/*
fetch(urls.recent).then((response) => {
response.json().then((json) => {
var view = 'recent';
var html = json.map((user) => {
return (
<tr>
<td>
<img src={user.img} alt={user.username} />
{user.username}
</td>
<td>{user.recent}</td>
<td>{user.alltime}</td>
</tr>
);
}); // Close json.map block.
this.setState({
'data': { [view]: html },
});
}); // Close response.json block.
}); // Close fetch block.
*/
}
render() {
return (
<div>
<View view={this.state.view} />
<table>
{this.state.data[this.state.view]}
</table>
</div>
);
}
}
ReactDOM.render(<Main />, document.getElementById('app'));
img {
width: 2em;
height: 2em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<main id="app"></main>
Спасибо.
У меня было ощущение, что это связано с тем, что асинхронные функции не выполняются до следующей итерации цикла. Я на самом деле пробовал как 'let', так и' const' на 'url',' html' и даже 'userNumber'. Я полностью забыл о 'key'. Ясно, что мое понимание работы с асинхронными функциями - небольшая неделя. Спасибо! – Vince
youre welcome;) –