如何依次调用两个异步函数?
我是 JavaScript 新手,目前正在使用 React Native 中的 async/await。我有两个异步函数
getAsyncLocation
和
getParking
。
getAsyncLocation
从设备以及路由参数(从另一个屏幕路由时获得)获取位置。
getParking
使用由
getAsyncLocation
分配的状态 -
mapRegion
- 来查找相关结果。
但是,当我一个接一个地运行它们时,我得到了:-
[Unhandled promise rejection: TypeError: null is not an object (evaluating 'mapRegion.latitude')]
我有以下代码:-
const [mapRegion, setmapRegion] = useState(null);
handleMapRegionChange = (mapRegion) => setmapRegion({ mapRegion });
const handleCenterChange = (lat, lng) => setmapRegion({
latitude: lat,
longitude: lng,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
})
async function getAsyncLocation() {
if (route.params) { // obtained from some other screen
handleCenterChange(route.params.lat, route.params.lng);
console.log("route params for location ", mapRegion.latitude, mapRegion.longitude);
}
else {
const { status, permissions } = await Permissions.askAsync(
Permissions.LOCATION
);
if (status === "granted") {
sethasLocationPermission(true);
let location = await Location.getCurrentPositionAsync({});
setlocationResult(JSON.stringify(location));
handleCenterChange(location.coords.latitude, location.coords.longitude);
} else {
alert("Location permission denied");
}
}
}
async function getParkings() {
console.log("get parking runing")
console.log("get parkig ", mapRegion.latitude, ", ", mapRegion.longitude);
await axios.get(`http://${MyIp}:8080/booking/findParking`, {
params: {
lat: mapRegion.latitude,
lng: mapRegion.longitude,
rad: 10
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
})
.then((response) => {
let parkingSpace = response.data;
let parking = []
for (let i = 0; i < parkingSpace.length; i++) {
parking.push({
spaceId: parkingSpace[i]._id,
ownerId: parkingSpace[i].owner,
location:
{ latitude: parkingSpace[i].latitude, longitude: parkingSpace[i].longitude }
})
}
console.log(parking)
setSpace(parking);
})
.catch((err) => {
console.log(err)
})
}
async function getData() {
await getAsyncLocation();
await getParkings();
}
useEffect(() => {
getData();
}, []);
我曾尝试在各种博客和 stackoverflow 问题中搜索它,但找不到解决方法。非常感谢任何提示。
您可以使用另一个 useEffect 钩子来观察 mapRegion 状态是否已更改。(您可以在应用中拥有任意数量的 useEffect 钩子)
useEffect(() => {
getAsyncLocation();
}, []); // [] without any args, this will be called only once. We want to get device location only once
useEffect(() => {
getParkings();
}, [mapRegion]) // since we have passed mapRegion as arg therefore it would be called whenever mapRegion is updated
你好,为了在
getParkings
之前执行
getAsyncLocation
,您必须使用 Promise。但还有另一个问题:即使您按顺序运行
getAsyncLocation
和
getParkings
,也不能保证
getParkings
中的
mapRegion
具有由
getAsyncLocation
设置的值(因为 Hooks 是异步的!)。那么如何解决您的问题?您有几种选择。一种是像这样使用 2 个 useEffect:
useEffect(() => {
getAsyncLocation();
}, []);
useEffect(() => {
getParkings();
}, [mapRegion]);
这种方法有两个问题:
-
每次加载包含
useEffect
的组件时,都会触发第一个 useEffect(也许您不希望这样)。 -
每次
mapRegion
更改其值时,都会触发第二个useEffect
(也许您不希望这样)。
因此,我建议使用 Promise 方法,正如我所说,但传递
getParkings
所需的值作为
getAsyncLocation
的结果。您的代码变为:
getAsyncLocation
async function getAsyncLocation() {
return new Promise(resolve => {
let result = {lat: -1, lng: -1};
if (route.params) { // obtained from some other screen
handleCenterChange(route.params.lat, route.params.lng);
console.log("route params for location ", mapRegion.latitude, mapRegion.longitude);
result.lat = route.params.lat;
result.lng = route.params.lng;
resolve(result);
return;
}
else {
const { status, permissions } = await Permissions.askAsync(
Permissions.LOCATION
);
if (status === "granted") {
sethasLocationPermission(true);
let location = await Location.getCurrentPositionAsync({});
setlocationResult(JSON.stringify(location));
handleCenterChange(location.coords.latitude, location.coords.longitude);
result.lat = location.coords.latitude;
result.lng = location.coords.longitude;
resolve(result);
return;
} else {
alert("Location permission denied");
}
}
resolve(result);
});
}
getParkings
async function getParkings(myMapRegion) {
return new Promise(resolve => {
console.log("get parking runing")
console.log("get parkig ", myMapRegion.lat, ", ", myMapRegion.lng);
await axios.get(`http://${MyIp}:8080/booking/findParking`, {
params: {
lat: myMapRegion.lat,
lng: myMapRegion.lng,
rad: 10
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
})
.then((response) => {
let parkingSpace = response.data;
let parking = []
for (let i = 0; i < parkingSpace.length; i++) {
parking.push({
spaceId: parkingSpace[i]._id,
ownerId: parkingSpace[i].owner,
location:
{ latitude: parkingSpace[i].latitude, longitude: parkingSpace[i].longitude }
})
}
console.log(parking)
setSpace(parking);
})
.catch((err) => {
console.log(err)
})
resolve();
});
}
getData
async function getData() {
let myMapRegion = await getAsyncLocation();
await getParkings(myMapRegion);
}