【发布时间】:2020-12-21 23:21:04
【问题描述】:
我有一个使用用户位置的应用。使用 Expo 的位置库,这就是我的代码的结构。
在主屏幕中,我创建了一个回调函数并包含在 useCallback HOC 中。
const userLocationCallback = useCallback(async (location) => {
// if we don't have any locations....fetch them and then sort them
if (!businessLocations || businessLocations.length <= 0) {
// todo check for wifi connectivity or data
let fetchedLocations = await fetchAllLocations();
sortByClosestLocation(location, fetchedLocations, updateLocations)
if (fetchedLocations.length >= 5) {
setListOfClosest(getFirstFromList(5, businessLocations))
}
} else {
sortByClosestLocation(location, businessLocations, updateLocations)
if (businessLocations.length >= 5) {
setListOfClosest(getFirstFromList(5, businessLocations))
}
}
}, [businessLocations, locationServicesOn, permissionGranted]);
每次更新时都会使用用户的位置调用此代码。这段代码中唯一真正重要的部分是对 await fetchAllLocations 的调用。这是对返回 JSON 的服务器的 api 调用。
这是自定义钩子的代码:
export default (
shouldTrackLocation,
timeBetweenUpdates,
callback,
locationServicesOn,
permissionGranted) => {
const [locationError, setLocationError] = useState(null);
let time = 0;
useEffect(() => {
let subscriber;
const startWatching = async () => {
try {
subscriber = await watchPositionAsync({
accuracy: Accuracy.BestForNavigation,
// timeInterval and distanceInterval seem to have no effect, but you must have distanceInterval === 0
timeInterval: 10000,
distanceInterval: 0
}, (location) => {
if (time === 0 || new Date().getTime() >= time + timeBetweenUpdates) {
callback(location).catch(e => {
console.log("Location Error: ", "caught the error here")
throw e;
});
time = new Date().getTime();
}
}
);
} catch (e) {
console.log("Location Error: ", "caught error in catch block")
setLocationError(e);
}
};
if (shouldTrackLocation && locationServicesOn && permissionGranted) {
startWatching().catch(err => {
console.log(err);
subscriber?.remove();
subscriber = null
})
} else {
subscriber?.remove();
subscriber = null;
}
return () => {
subscriber?.remove();
}
}, [shouldTrackLocation, callback, locationServicesOn, permissionGranted]);
return [locationError];
}
我定义了一个函数startWatching,它使用了expo-location的函数watchPositionAsync。此处相关的代码部分是回调函数(传递给 watchPositionAsync 的第二个参数)。回调函数是我在顶部显示的代码——我在 useCallback 中包装的代码。从主屏幕(定义回调函数的地方)我这样调用钩子:
const [locationError] = useCurrentLocation(
screenIsFocused,
3000,
userLocationCallback,
locationServicesOn,
permissionGranted,
);
这就是问题所在。如果回调函数产生错误,我想捕捉它。但是,我正在进行 api 调用,如果服务器关闭并且回调由于它关闭而引发错误,那么为什么它没有显示在 startWatching 函数的 catch 块中?
如您所见,我尝试通过将 .catch(e => ....) 附加到调用末尾来立即捕获它。那行得通,但是当我在该块内抛出错误时,它永远不会碰到我试图调用setLocationError(e)的下面的catch块。
我似乎无法理解我的错误流程。如果应用程序无法连接到服务器,我想做点什么。帮助我理解为什么会跳过 catch 块。
【问题讨论】:
-
那么,您基本上是在问,如果出现网络错误或其他情况,您如何处理服务器端可能发生的错误?
-
不,我正在尝试处理客户端上的错误。如果服务器关闭,获取数据的 api 调用将失败,因为客户端将无法连接到服务器。如果我在我创建的 startWatching 函数中添加 callback(location).catch(e => console.log(e)) ,我能够在发生这种情况时捕获错误。但该错误永远不会传播到后续的 catch 块。
-
好的,同样的事情。我会为你的情况添加一个答案
标签: react-native error-handling async-await react-hooks