Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React中循环的内部异步函数_Javascript_Reactjs_Async Await - Fatal编程技术网

Javascript React中循环的内部异步函数

Javascript React中循环的内部异步函数,javascript,reactjs,async-await,Javascript,Reactjs,Async Await,我在React中有一段代码,它调用Dark Sky API并返回特定日期的天气数据。每个请求都有一个特定的日期。请求成功后,我通过setState将数据放入数组中。代码运行正常,但每个请求都是异步运行的,因此数据会按每个调用完成的顺序推送到数组中,因此不会给我一个有序的日期列表。代码如下: loadPreviousMonth = async () => { const current = {...this.state}; for (let i=30; i >= 1; i--

我在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);
  }
}

谢谢

您可以使用。。其中将按顺序运行:

async function processArray(array) {
  for (const item of array) {
    await darkSky(url, this.onTimeRequestSuccess, this.onError);
  }
 console.log('Done!');
}

你可以用。。其中将按顺序运行:

async function processArray(array) {
  for (const item of array) {
    await darkSky(url, this.onTimeRequestSuccess, this.onError);
  }
 console.log('Done!');
}

您可以尝试递归函数调用。大概是这样的:

function darkSky(url, onTimeRequestSuccess, onError) {
     return fecth(url).then(onTimeRequestSuccess).catch(onError);
}
var delay=ms=>newpromise(res=>setTimeout(res,ms));
函数执行器(迭代){
如果(迭代>0){
延迟(500)。然后(()=>{
console.log(迭代)
执行者(迭代-1)
})
}
}

ExecuteInoder(30)
您可以尝试递归函数调用。大概是这样的:

function darkSky(url, onTimeRequestSuccess, onError) {
     return fecth(url).then(onTimeRequestSuccess).catch(onError);
}
var delay=ms=>newpromise(res=>setTimeout(res,ms));
函数执行器(迭代){
如果(迭代>0){
延迟(500)。然后(()=>{
console.log(迭代)
执行者(迭代-1)
})
}
}
ExecuteInoder(30)
使用。Waaay比在循环中使用递归或等待更快,因为所有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
});
使用。Waaay比在循环中使用递归或等待更快,因为所有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
});

问题在于,没有什么可以确保一个请求在另一个请求之前完成,但这取决于函数
darkSky
的实现方式。据我所知,从您的代码中可以猜到,它将如下所示:

function darkSky(url, onTimeRequestSuccess, onError) {
     return fecth(url).then(onTimeRequestSuccess).catch(onError);
}
因为您正在使用
onTimeRequestSuccess
作为对
darkSky
内部承诺的解析,
processArray
中的等待不会等待获取承诺,而是等待
onTimeRequestSuccess
的结果。这就是为什么秩序得不到维持

如果您想保持顺序(在获取数据后不重新排序),并且不需要连续调用30次,一种方法是创建一个包含所有查询承诺的数组,使用
Promise.all
等待所有查询都被解析,然后将整个数组设置为状态。例如:

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}));
}

问题在于,没有什么可以确保一个请求在另一个请求之前完成,但这取决于函数
darkSky
的实现方式。据我所知,从您的代码中可以猜到,它将如下所示:

function darkSky(url, onTimeRequestSuccess, onError) {
     return fecth(url).then(onTimeRequestSuccess).catch(onError);
}
因为您正在使用
onTimeRequestSuccess
作为对
darkSky
内部承诺的解析,
processArray
中的等待不会等待获取承诺,而是等待
onTimeRequestSuccess
的结果。这就是为什么秩序得不到维持

如果您想保持顺序(在获取数据后不重新排序),并且不需要连续调用30次,一种方法是创建一个包含所有查询承诺的数组,使用
Promise.all
等待所有查询都被解析,然后将整个数组设置为状态。例如:

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}));
}

您不应该无序地保存状态中的数据,并在从状态中检索数据之后但在显示给用户之前对其进行排序吗。订购30个项目的数组只需几毫秒。但是,只有在收到当前api调用后才进行下一次api调用将永远需要进行30次api调用。我可以这样做,但我希望我可以按顺序运行每个api调用,这样我就不必采取额外的步骤。你应该采取额外的步骤,编辑了我以前的评论,添加了“为什么”。谢谢,我最后只是将数组排序在:)之后。您不应该将数据无序保存在您的状态中,并在从状态检索后但在显示给用户之前对其排序吗。订购30个项目的数组只需几毫秒。但是,只有在收到当前api调用后才进行下一个api调用将永远需要30个api调用。我可以这样做,但我希望我可以按顺序运行每个api调用,这样我就不必采取额外的步骤。你应该采取额外的步骤,编辑我以前的注释以添加“为什么”。谢谢,我只是在以下位置对数组进行排序:)