开发者问题收集

React Native 使用 for 循环内的 fetch

2017-04-01
3095

在我的 React Native 应用中,我有一个对象数组,每个对象都有 3 个属性:地址、纬度和经度。纬度和经度最初为空,因此我使用 Google API 进行反向地理编码。由于它是一个数组,因此我在数组内循环并获取 Google URL 以从给定地址获取纬度和经度。但是当我尝试在对象中保存纬度和经度时,出现错误:

TypeError: undefined is not an object (evaluating: locations[i].latitude = responseJson.results[0].geometry.location.lat)

这是我的代码:

for (var i = 0; i < locations.length; i++){

          if (locations[i].address){

            var googleRequestUrl = this.state.GoogleAPIUrl + locations[i].address;

            fetch(googleRequestUrl)
            .then((response) => response.json())
            .then((responseJson) => {
              locations[i].latitude = responseJson.results[0].geometry.location.lat;
              locations[i].longitude = responseJson.results[0].geometry.location.lng;
            })
            .catch((error) => {
              console.warn(error);
            })
            .done();
          }
        }

我使用的谷歌 API 是:“ https://maps.googleapis.com/maps/api/geocode/json?address=

我已经使用 response.text() 检查过是否收到了响应:它给出了完整的响应,包括纬度和经度。

我不明白为什么会出现这个错误,我做错了什么?在循环中进行提取有什么问题吗?还是其他问题?

任何建议或更好的解决方案都值得赞赏

2个回答

可能您的某个地址无法正确地理编码,并且您正尝试访问响应对象上不存在的结果。

我会检查结果是否存在并继续执行。

const result = responseJson.results[0];
if (result) {
    locations[i].latitude = result.geometry.location.lat;
    locations[i].longitude = result.geometry.location.lng;
}
Andreyco
2017-04-01

此代码:

.then((responseJson) => {
    locations[i].latitude = responseJson.results[0].geometry.location.lat;
    locations[i].longitude = responseJson.results[0].geometry.location.lng;
})

不会执行您想要的操作。

由于此代码异步运行,它将使用在执行时找到的 i 的值。当您从服务器收到响应时,您的 for 循环将已经完成执行。for 循环末尾的 i 值是什么?它将是 4。

因此,您将尝试将值(对于每个提取)存储在未定义的 locations[4] 中。

要解决此问题,您可以做几件事:
1. 如果您使用的是 ES6,最简单的方法是在 for 循环中声明一个等于循环变量的常量。这基本上会在索引上创建一个闭包,以允许您稍后引用正确的值。它看起来会像这样:

for (var i = 0; i < locations.length; i++){
    if (locations[i].address){
        var googleRequestUrl = this.state.GoogleAPIUrl + locations[i].address;

        const index = i;
        fetch(googleRequestUrl)
        .then((response) => response.json())
        .then((responseJson) => {
            locations[index].latitude = responseJson.results[0].geometry.location.lat;
            locations[index].longitude = responseJson.results[0].geometry.location.lng;
        })
        .catch((error) => {
            console.warn(error);
        })
        .done();
    }
}
  1. 将循环变量传递给另一个获取数据并执行更改的函数

  2. 使用基本上执行 #2 但带有匿名函数的数组映射函数

```

locations.map((location) => {
    if (location.address) {
        var googleRequestUrl = this.state.GoogleAPIUrl + location.address;
        fetch(googleRequestUrl)
        .then((response) => response.json())
        .then((responseJson) => {
            location.latitude = responseJson.results[0].geometry.location.lat;
            location.longitude = responseJson.results[0].geometry.location.lng;
        })
        .catch((error) => {
            console.warn(error);
        })
        .done();
    }
);
Garrett McCullough
2017-04-03