我遇到了从forEach循环中的嵌套axios调用更新状态的问题:
constructor(props) {
super(props);
this.state = {
isLoaded: false,
items: []
};
//Binding fetch function to component's this
this.fetchFiles = this.fetchFiles.bind(this);
}
componentDidMount() {
this.fetchFiles();
}
fetchFiles() {
axios.get('/list')
.then((response) => {
var items = response.data.entries;
items.forEach((item, index) => {
axios.get('/download'+ item.path_lower)
.then((response) => {
item.link = response.data;
})
.catch(error => {
console.log(error);
})
});
this.setState(prevState => ({
isLoaded: true,
items: items
}));
console.log(this.state.items);
})
.catch((error) => {
console.log(error);
})
}
我们的想法是使用它的API(JavaScript SDK)从Dropbox获取所有项目 然后对于每个项目,我还需要调用不同的API端点来获取临时下载链接并将其指定为新属性。只有在所有项目都将附加其链接之后,我才想要setState并渲染组件。有人可以帮忙解决这个问题吗,我花了好几个小时与承诺作斗争:S
答案 0 :(得分:1)
您可以使用Promise.all
等待多个承诺。另请注意,setState
是异步的,您不会立即看到更改。你需要传递一个回调。
fetchFiles() {
axios.get('/list')
.then((response) => {
var items = response.data.entries;
// wait for all nested calls to finish
return Promise.all(items.map((item, index) => {
return axios.get('/download'+ item.path_lower)
.then((response) => {
item.link = response.data;
return item
});
}));
})
.then(items => this.setState(prevState => ({
isLoaded: true,
items: items
}), () => console.log(this.state.items)))
.catch((error) => {
console.log(error);
})
}
答案 1 :(得分:0)
尝试通过添加 async 关键字将fetchfiles()函数作为异步方法。现在,我们必须等到项目获取其下载链接,因此添加 await < / strong>关键字在该行之前使代码等待,直到axios调用完成。
async function fetchFiles() {
axios.get('/list')
.then(async function(response){
var items = response.data.entries;
await items.forEach((item, index) => {
axios.get('/download'+ item.path_lower)
.then((response) => {
item.link = response.data;
})
.catch(error => {
console.log(error);
})
});
this.setState(prevState => ({
isLoaded: true,
items: items
}));
console.log(this.state.items);
})
.catch((error) => {
console.log(error);
})
}
我还没有对代码进行测试,但它应该可以正常运行。