'Firebase V9 does not give error in catch when offline
Solution 1:[1]
This is by design thanks to Firestore's Offline Behaviour (queued up to the right spot, but I do recommend watching in full).
The promise will resolve once the server has acknowledged the request. If the server is currently unavailable, that request is cached within the SDK and attempted as soon as a connection is restored. During this window, the Promise will be kept in its pending state because that's the state its actually in - pending. While the promise may not resolve, all your local realtime listeners and such will still fire off and your app will function as normal - just offline.
Dealing with this behaviour is an exercise for the developer. One way to approach this would be to use Promise.race()
to implement your own offline-handling logic.
As a quick & dirty example, here's a setDocWithTimeout
implementation:
const setDocWithTimeout = (ref, data, options) => {
const timeoutMS = options && options.timeout || 10000;
const setDocPromise = setDoc(ref, data);
return Promise.race([
setDocPromise.then(() => ({ timeout: false })),
new Promise((resolve, reject) => setTimeout(resolve, timeoutMS, { timeout: true, promise: setDocPromise }));
]);
}
which you can apply using:
try {
const result = await setDocWithTimeout(doc(db, "cities", "new-city-2"), data);
if (result.timeout) {
// offline? (could be poor connection too)
console.log("Document added to Firestore queue");
// dismiss any blocking UIs/loading bubbles
// tell user will be written to server later
await result.promise; // wait for write to complete as before
}
// online! (or back online)
console.log("Document written successfully!");
} catch (err) {
console.error(`error found! ${err}`);
}
Alternatively where an error is thrown:
const setDocWithTimeoutError = (ref, data, options) => {
const timeoutMS = options && options.timeout || 10000;
const setDocPromise = setDoc(ref, data);
return Promise.race([
setDocPromise,
new Promise((_, reject) => setTimeout(reject, timeoutMS, new Error("timeout"));
]);
}
which you can apply using:
try {
await setDocWithTimeoutError(doc(db, "cities", "new-city-2"), data);
console.log("Document written successfully!");
} catch (err) {
console.error(`error found! ${err}`);
}
Solution 2:[2]
works on web v9, see docs from v8.
import { onLog } from 'firebase/app';
onLog((e) => {
const { level, message } = e;
if (level === 'warn') {
console.log('connection interruption after intial load was success:', message);
}
if (level === 'error') {
console.log('no connection on inital load:', message);
}
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | samthecodingman |
Solution 2 | wenzf |