我在React中有这段代码,该代码调用Dark Sky API,并返回特定日期的天气数据。每个请求都有一个特定的日期。一旦请求成功,我将通过setState将数据放入数组中。代码运行良好,但是每个请求都是异步运行的,因此,数据将按照每个调用完成的顺序推送到数组中,因此不会得到我的订购日列表。这是代码:
loadPreviousMonth = async () => {
const current = {...this.state};
for (let i=30; i >= 1; i--) {
const date = new Date();
const previousDay = Math.floor(date.setDate(date.getDate() - i) / 1000);
const url = `/api/darksky?latitude=${current.latitude}&longitude=${current.longitude},${previousDay}`;
await darkSky(url, this.onTimeRequestSuccess, this.onError);
}
}
谢谢!
答案 0 :(得分:2)
您可以使用..其中将按顺序运行:
async function processArray(array) {
for (const item of array) {
await darkSky(url, this.onTimeRequestSuccess, this.onError);
}
console.log('Done!');
}
答案 1 :(得分:2)
使用Promise.all。比所有循环中使用递归或等待更快,因为所有API调用将同时发生,而不是顺序发生。
const promises = [];
for (let i=30; i >= 1; i--) {
const date = new Date();
const previousDay = Math.floor(date.setDate(date.getDate() - i) / 1000);
const url = `/api/darksky?latitude=${current.latitude}&longitude=${current.longitude},${previousDay}`;
promises.push(darkSky(url, this.onTimeRequestSuccess, this.onError));
}
Promise.all(promises).then(arrOfResults => {
// setState here
});
答案 2 :(得分:1)
问题在于,没有什么可以确保一个请求先于另一个请求完成,但这取决于如何实现函数darkSky
。据我从您的代码中猜测,它看起来像这样:
function darkSky(url, onTimeRequestSuccess, onError) {
return fecth(url).then(onTimeRequestSuccess).catch(onError);
}
因为您使用onTimeRequestSuccess
来解决darkSky
内部的承诺,所以processArray
中的await不会等待获取承诺,而是会等待onTimeRequestSuccess
的结果。这就是为什么不保留订单的原因。
如果要保持顺序(获取数据后不重新排序)并且不具有连续30次调用的链,则一种方法可以是创建一个具有所有查询的诺言的数组,等待使用来解决所有问题Promise.all
,然后将整个数组设置为state。例如:
loadPreviousMonth = () => {
const current = {...this.state};
const promises = [];
for (let i=30; i >= 1; i--) {
const date = new Date();
const previousDay = Math.floor(date.setDate(date.getDate() - i) / 1000);
const url = `/api/darksky?latitude=${current.latitude}&longitude=${current.longitude},${previousDay}`;
promises.push(fetch(url));
}
Promise.all(promises).then((results) => this.setState({results: results}));
}
答案 3 :(得分:0)
您可以尝试递归函数调用。像这样的东西:
var delay = ms => new Promise(res => setTimeout(res, ms));
function executeInOrder(iteration){
if(iteration>0){
delay(500).then(()=>{
console.log(iteration)
executeInOrder(iteration-1)
})
}
}
executeInOrder(30)