'Firebase V9 does not give error in catch when offline

I want to set state in catch even if user offline but firebase V9 setDoc does not give anything in catch when user offline

I want to set state in catch even if user offline but firebase V9 setDoc does not give anything in catch when user offline

For Example: in Authentication, if the user offline firebase gives (network error) in catch but in firestore "add document" no message from catch...



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