14

I recently updated my app from firebase to firestore but stuck at offline persistance. I am using react-native-firebase to integrate firestore and disable its perisistance but still not getting any catch error when no internet. This is my code to delete data but catch never gets error when no internet not is the promise resolved.

firebase.firestore().collection('d').doc(deviceid).delete().then(function () {
                                    console.log("Device Deleted");
                                    that.setState({
                                        loading: false
                                    });
                                    Toast.show('Device Deleted Succesfully', {
                                        duration: Toast.durations.SHORT,
                                        position: Toast.positions.TOP,
                                        shadow: true,
                                        animation: true,
                                        hideOnPress: true,
                                        delay: 0,
                                    });

                                }).catch(function (err) {
                                    console.log(err);
                                    that.setState({
                                        loading: false
                                    });
                                })
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Honney Goyal
  • 247
  • 1
  • 5
  • 13

3 Answers3

21

Firestore and Realtime Database SDKs don't throw errors when there is no network connectivity. They will silently retry the connection in hopes that the device will regain network connectivity soon. The reason for this is because most developers don't want their apps to appear broken just because the user went into a tunnel and back out, or switched between mobile towers in a way that forced a network reset.

In order to effectively make use of an online database, the device should be online most of the time, and this the situation that the SDK is optimizing for.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • Thanks Doug for quick response. I want to delete a document only when device is online. As other people will be simultaneously using the same document. So is there any work around for this. – Honney Goyal May 26 '18 at 14:29
  • You could use Cloud Functions to define an HTTP function that you can call from the client that performs the work. – Doug Stevenson May 26 '18 at 14:37
  • I thought of that but wont that be unnecessary as i can update firestore without calling an api. – Honney Goyal May 26 '18 at 14:42
  • 1
    Since methods like `get` return a promise and in a case the user is temporarily offline the promise `resolves` even though the request failed while the sdk is silently retrying in the background. The issue is that the retry operation is cut off from the app state updating mechanism. It would make sense to keep the loading state displayed while retrying, however since the promise resolved long ago, how is the app going to recover. The only logical paths seems to be to either not resolve or reject the promise until the request succeeds or return an observable. What do you think? – Mateja Petrovic Jul 01 '20 at 23:44
7

Make your own helper function for deletion that throws an error if there is no Internet connection. You can make the API cleaner by not calling .collection() but rather passing the full path d + deviceid to it.

function onlineOnlyDelete(path) {
  if(!deviceApi.hasInternet()) throw 'No Internet, no delete'
  return firebase.firestore().doc(path).delete()
}

replace firebase.firestore().collection('d').doc(deviceid) with onlineOnlyDelete(d+deviceid) and you should be good to go

Riku Räisänen
  • 158
  • 1
  • 4
  • I like this method. Loose coupling with firebase yet can be as granular as one wants. It works very well with [`react-native-netinfo`](https://github.com/react-native-netinfo/react-native-netinfo). – Fanchen Bao Jun 14 '21 at 21:11
5

Referencing this thread. I set up the following check:

.then(() => {
  if (snapshot.empty && snapshot.metadata.fromCache) {
     throw new Error('Failed to fetch ideas');
  }
})

Then later on I caught the error and set the app state to include the error along with parameters specific to the batch like startIndex and stopIndex which will be important later. When rendering the documents, one case is reserved for the BatchError as I dubbed it, in which case the user is going to see a Refetch button which has a callback attached to it. Using the batch metadata, the callback is able to reinitialize the specific batch request.

Mateja Petrovic
  • 3,799
  • 4
  • 25
  • 40