The Realtime Database API in Firebase is based on callbacks. This could be fine for you if you are maintaining a codebase which is a few years old.
But, if you prefer a Promise
, or better yet async await
approach, you will be down for a little disappointment.
A typical function that you write for retrieving data from a particular path in the Realtime database will look like as follows:
const admin = require("firebase-database");
const realtimeDb = admin.database();
const ref = realtimeDb.ref(`/path/to/the/data`);
/** Called on `value` event */
const onDataCallback = (data) => {
// Do whatever you want with the data
console.log("data:", data);
};
ref.on("value", onDataCallback);
We are dealing with callbacks here, so we cannot use then()
, or await
for our async operations.
Let us start with an example.
Let’s suppose, you want to fetch data from the path:
/Users/usernames/hopelesspuppy
For that, you would first need to create a reference to this path.
const ref = admin.database().ref("/Users/usernames/hopelesspuppy");
Suppose you want to fetch some data from a certain path from the Realtime Database. To fetch the data using the ref
, you would write your code as follows:
const getData = ref => {
return Promise((resolve, reject) => {
const onData = data => resolve(data));
const onError = error => reject(error));
ref.on('value', onData, onError);
});
};
If you have read the docs, you’d know how this code works.
But, for the uninitiated, let me reiterate.
ref.on("value", onData, onError);
The ref
denotes the reference to the item in the database which you want to perform an action like read or write.
When you set a value
event on the item reference in the Realtime database, one of the callbacks you provide will be called.
In this instance, I have named my callbacks onData
and onError.
As the name suggests, if the retrieval is successful, the onData
function will execute with the snapShot
of the object. You can access its value using the .val()
method on that snapshot.
In case of an error, your the onError
function will execute where I’m only printing the error as a string.
const onData = (snapShot) => {
console.log(snapShot.val());
};
const onError = (error) => {
console.log("Error retrieving the data:", error.toString());
};
So, how do we convert this callback-based code into a Promise
.
The answer is simple. Use the Promise
constructor.
Or to be more precise, you just wrap your callback code into a Promise
constructor. This constructor resolve
s or reject
s based on onData
or onError
callback execution.
Here’s the code:
const getData = (ref) => {
return new Promise((resolve, reject) => {
const onError = error => reject(error);
const onData = snap => resolve(snap.val());
ref.on("value", onData, onError);
});
};
getData(ref)
.then((value) => {
// resolve() was called
})
.catch((error) => {
// reject() was called
// Something went wrong while fetching the data.
// Handle that error here.
});
That is all.
Leave a Reply