ReactJS:在带有ajax调用的.map()语句之后执行代码

时间:2022-04-01 15:55:53

I'm stuck at a problem with my twitch tv api app for freecodecamp.

我遇到了freecodecamp的twitch tv api应用程序的问题。

I have a .map() statement with an ajax call in it. And I push the data I get from the call into an array.

我有一个带有ajax调用的.map()语句。我将从调用中得到的数据推送到数组中。

I want to set the state of the app to the array after the whole .map() loop is finished but somehow the Array is always empty when I access it outside of .map()

我希望在整个.map()循环完成后将应用程序的状态设置为数组但是当我在.map()之外访问它时,数组总是空的

Here is the code I tried.

这是我试过的代码。

getData() {
  let tempArray= [];
  let self = this;
  STREAMER.map(function(streamer, i) {
    $.ajax({
      url: URL + streamer,
      success: (data) => {
        tempArray.push(data);
      },
      dataType: "jsonp"
    })
  });
  this.setState({data: tempArray});
}

I got the feeling that the problem is that the ajax call is asynchronous obv. But I thought since I call the this.setState() method outside of the .map() loop which should be synchronous everything should be fine but isn't.

我觉得问题是ajax调用是异步的obv。但我想,因为我在.map()循环之外调用this.setState()方法应该是同步的,所以一切都应该没问题,但事实并非如此。

The Ajax call isn't the problem btw. If I log the data inside of the success method everything is exactly how I like it.

Ajax调用不是btw的问题。如果我在成功方法中记录数据,那么一切都是我喜欢的。

Any Ideas?

有任何想法吗?

2 个解决方案

#1


2  

Use your .map() call to return the promises from all the $.ajax() calls. You can then use $.when() to wait for them to complete:

使用.map()调用返回所有$ .ajax()调用的promise。然后,您可以使用$ .when()等待它们完成:

getData() {
  let tempArray= [];
  let self = this;
  $.when.apply($, STREAMER.map(function(streamer, i) {
    return $.ajax({
      url: URL + streamer,
      success: (data) => {
        tempArray.push(data);
      },
      dataType: "jsonp"
    })
  }).then(function() {}
    self.setState({data: tempArray});
  });
}

The returned promises will be gathered up into an array by .map(). The returned array is then passed via .apply() into $.when(). That'll manage waiting for all the promises, and your .then() callback will be invoked when they're all done.

返回的promise将由.map()收集到一个数组中。然后返回的数组通过.apply()传递到$ .when()。那将管理等待所有的承诺,并且当他们全部完成时,你的.then()回调将被调用。

If it's at all possible, I suggest you look into the possibility of doing the iteration work at the server and providing a single HTTP API that processes a group of items and returns an aggregate result. HTTP requests take time, and browsers will only do a limited number of them concurrently. One issue in particular with this approach is that the order of the "temp" array will not necessarily match the order of the original array. That is, when the process is done, tempArray[2] may or may not contain the result from the ajax call for STREAMER[2]. There's no guarantee that the HTTP requests will complete in the order that they were issued; in fact if you're doing more than a few, then it's very very likely that they'll complete out of order.

如果可能的话,我建议您研究在服务器上进行迭代工作的可能性,并提供一个HTTP API来处理一组项目并返回聚合结果。 HTTP请求需要时间,浏览器只会同时执行有限数量的HTTP请求。特别是这种方法的一个问题是“temp”数组的顺序不一定与原始数组的顺序相匹配。也就是说,当进程完成时,tempArray [2]可能包含也可能不包含来自STREAMER [2]的ajax调用的结果。无法保证HTTP请求将按照发出的顺序完成;事实上,如果你做的不止一些,那么它们很可能完全无序。

#2


0  

SIMPLE SOLUTION

简单的解决方案

The setState() function should be called inside the success callback of async ajax request.

应该在异步ajax请求的成功回调中调用setState()函数。

getData() {
  let tempArray= [];
  let self = this;
  STREAMER.map(function(streamer, i) {
    $.ajax({
      url: URL + streamer,
      success: (data) => {
        tempArray.push(data);
        if(i === STREAMER.length - 1) {
          self.setState({data: tempArray});
        }
      },
      dataType: "jsonp"
    })
  });
}

USE PROMISE

使用承诺

When all ajax requests are successful, resolve the Promise and setState inside resolve().

当所有ajax请求都成功时,在resolve()中解析Promise和setState。

#1


2  

Use your .map() call to return the promises from all the $.ajax() calls. You can then use $.when() to wait for them to complete:

使用.map()调用返回所有$ .ajax()调用的promise。然后,您可以使用$ .when()等待它们完成:

getData() {
  let tempArray= [];
  let self = this;
  $.when.apply($, STREAMER.map(function(streamer, i) {
    return $.ajax({
      url: URL + streamer,
      success: (data) => {
        tempArray.push(data);
      },
      dataType: "jsonp"
    })
  }).then(function() {}
    self.setState({data: tempArray});
  });
}

The returned promises will be gathered up into an array by .map(). The returned array is then passed via .apply() into $.when(). That'll manage waiting for all the promises, and your .then() callback will be invoked when they're all done.

返回的promise将由.map()收集到一个数组中。然后返回的数组通过.apply()传递到$ .when()。那将管理等待所有的承诺,并且当他们全部完成时,你的.then()回调将被调用。

If it's at all possible, I suggest you look into the possibility of doing the iteration work at the server and providing a single HTTP API that processes a group of items and returns an aggregate result. HTTP requests take time, and browsers will only do a limited number of them concurrently. One issue in particular with this approach is that the order of the "temp" array will not necessarily match the order of the original array. That is, when the process is done, tempArray[2] may or may not contain the result from the ajax call for STREAMER[2]. There's no guarantee that the HTTP requests will complete in the order that they were issued; in fact if you're doing more than a few, then it's very very likely that they'll complete out of order.

如果可能的话,我建议您研究在服务器上进行迭代工作的可能性,并提供一个HTTP API来处理一组项目并返回聚合结果。 HTTP请求需要时间,浏览器只会同时执行有限数量的HTTP请求。特别是这种方法的一个问题是“temp”数组的顺序不一定与原始数组的顺序相匹配。也就是说,当进程完成时,tempArray [2]可能包含也可能不包含来自STREAMER [2]的ajax调用的结果。无法保证HTTP请求将按照发出的顺序完成;事实上,如果你做的不止一些,那么它们很可能完全无序。

#2


0  

SIMPLE SOLUTION

简单的解决方案

The setState() function should be called inside the success callback of async ajax request.

应该在异步ajax请求的成功回调中调用setState()函数。

getData() {
  let tempArray= [];
  let self = this;
  STREAMER.map(function(streamer, i) {
    $.ajax({
      url: URL + streamer,
      success: (data) => {
        tempArray.push(data);
        if(i === STREAMER.length - 1) {
          self.setState({data: tempArray});
        }
      },
      dataType: "jsonp"
    })
  });
}

USE PROMISE

使用承诺

When all ajax requests are successful, resolve the Promise and setState inside resolve().

当所有ajax请求都成功时,在resolve()中解析Promise和setState。