我有一个使用用户位置的应用程序。使用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块。
答案 0 :(得分:0)
对于您的特定情况,您可以如下修改您的自定义:
export default (
shouldTrackLocation,
timeBetweenUpdates,
callback,
locationServicesOn,
permissionGranted) => {
const [locationError, setLocationError] = useState(null);
let time = 0;
const innerLocationCallback = useCallback(async (location) => {
try {
if (time === 0 || new Date().getTime() >= time + timeBetweenUpdates) {
callback(location);
time = new Date().getTime();
}
}
catch (e) {
setLocationError(e);
}
}, []);
useEffect(() => {
let subscriber;
const startWatching = async () => {
try {
subscriber = await watchPositionAsync({
accuracy: Accuracy.BestForNavigation,
timeInterval: 10000,
distanceInterval: 0
}, innerLocationCallback
);
} 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];
}
我不想事先对您的代码进行重大更改,因为它有点复杂。 但是我个人不会这样调用我的外部回调。如果这对您有用,我可以稍后再回答。