与内部的另一个异步 api 调用反应 Native GeoLocation 不起作用
Posted
技术标签:
【中文标题】与内部的另一个异步 api 调用反应 Native GeoLocation 不起作用【英文标题】:ReactNative GeoLocation with another asynchronous api call inside not working 【发布时间】:2017-10-02 22:10:14 【问题描述】:我正在使用地理定位来获取当前坐标(纬度和经度)。当坐标可用时,我希望能够使用返回的坐标进行 API 调用。 但是,由于某种原因,API 调用没有正确执行。在地理定位返回坐标后立即进行 API 调用的正确方法是什么? 这是代码:
const that = this;
//Getting the current location using the geolocation API
navigator.geolocation.getCurrentPosition(
(position) =>
this.setState(
latitude: position.coords.latitude,
longitude: position.coords.longitude,
error: null
);
//Here is the API call to be executed after the coordinates are returned and state is set for the latitude and longitude
const url = 'http://sewoa-easy-breezy-home-number-api-us1.smx.online/api/v1/houses/number?latitude=' + that.state.latitude
+ '&longitude=' + that.state.longitude;
axios.get(url).then(function (response)
if (response.data)
Actions.viewHouseNumber( houseNumber: response.data.number );
else
Actions.houseNotFound( latitude: that.state.latitude, longitude: that.state.longitude );
).catch(() =>
// The request was made, but the server responded with a status code
// that falls out of the range of 2xx
if (that.state.latitude && that.state.longitude)
Actions.houseNotFound( latitude: that.state.latitude, longitude: that.state.longitude );
else
Actions.error( message: 'connection_error');
);
,
(error) =>
Actions.error( message: 'gps_error' );
return;
,
enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 ,
)
这里使用的 navigation.getCurrentPostion 和 axios.get 方法都是分开工作的。然而,既然 API 调用在 gelocation.getCurrentPosition 方法中,整个事情就不起作用了。关于如何解决这个问题的任何想法?
【问题讨论】:
【参考方案1】:在 React 中,setState 是异步的。这意味着它不会立即执行,而是要等到下一个更新周期才能真正执行。这对用户来说通常是不可见的,但这意味着that.state.latitude
和that.state.longitude
可能是未定义的。在调用 setState 后立即尝试 console.log(that.state.latitude, that.state.longitude)
。
解决方案:setState 接受回调作为第二个参数。您可以将依赖于状态新值的所有代码部分放在所述回调中。这将确保在运行这些行之前已更新状态。
这可能看起来像这样(假设您发布的 sn-p 位于组件的 componentWillMount 方法中):
class MyComponent extends Component
fetchHouseNumber = () =>
const url = 'http://sewoa-easy-breezy-home-number-api-us1.smx.online/api/v1/houses/number?latitude=' + this.state.latitude
+ '&longitude=' + this.state.longitude;
axios.get(url).then(function (response)
if (response.data)
Actions.viewHouseNumber( houseNumber: response.data.number );
else
Actions.houseNotFound( latitude: this.state.latitude, longitude: this.state.longitude );
componentWillMount()
//Getting the current location using the geolocation API
navigator.geolocation.getCurrentPosition(
(position) =>
this.setState(
latitude: position.coords.latitude,
longitude: position.coords.longitude,
error: null,
, () => this.fetchHouseNumber()); // The callback I'm talking about
(error) =>
Actions.error( message: 'gps_error' );
,
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 1000
)
旁注:你为什么使用that
而不是这个?由于您使用的是箭头函数,因此您不需要保护this
的值。另外,我没有看到在您的 sn-p 中分配了 that
。难道你的问题不是来自这个吗?
编辑:性能
正如 cmets 中所述,在 setState 上使用回调可能会很昂贵。如果您想尽快触发 API 调用,在等待触发 setState 回调之前,您可以这样做:
class MyComponent extends Component
fetchHouseNumber = (latitude, longitude) =>
const url = 'http://sewoa-easy-breezy-home-number-api-us1.smx.online/api/v1/houses/number?latitude=' + latitude
+ '&longitude=' + longitude;
axios.get(url).then(function (response)
if (response.data)
Actions.viewHouseNumber( houseNumber: response.data.number );
else
Actions.houseNotFound( latitude, longitude );
componentWillMount()
//Getting the current location using the geolocation API
navigator.geolocation.getCurrentPosition(
(position) =>
const latitude, longitude = position.coords; // destructuring assignment
this.fetchHouseNumber(latitude, longitude);
this.setState(
latitude, // object property shorthand
longitude,
error: null
);
(error) =>
Actions.error( message: 'gps_error' );
,
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 1000
)
这样,一旦地理定位数据可用,您就会触发回调,但如果组件中的其他地方需要地理定位数据,您仍然可以将其置于状态(如果不需要,您可以删除 setState 部分...)。
【讨论】:
这是一个我忘记复制的上限范围变量,但我只是对其进行了编辑。在这种情况下,您将如何准确编写 setState 方法(代码方面)? 我刚刚添加了一个sn-p。对不起,我后来发现我的解释很抽象 但是that
可能不需要,因为您正在使用箭头函数。仅使用 this
并仅声明箭头函数(如果可能)通常比携带 self
、that
或 _this
或在您需要访问回调内部组件的范围时容易得多。
虽然这个答案显示了正确使用setState
的好方法,但您可以只使用position
对象中的值,而不是尝试从状态中读取它们。这将有助于不等待状态设置来进行 API 调用。可能相差几毫秒,但这是另一种思考方式。
@bennygenel 完全正确。我正在编辑 sn-p 考虑到这个性能问题。以上是关于与内部的另一个异步 api 调用反应 Native GeoLocation 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
如何取消 useEffect 清理函数中的所有订阅和异步任务?