Home > database >  Infinite Loop RealtimeDatabase insertion
Infinite Loop RealtimeDatabase insertion

Time:09-15

Recently, I've started using realtime database and functions for my project. I was trying to retrieve information from an API and then, store it into my realtime database. I am going to show you and explaint to you the code.

this is the function to get the data from API. Working great.

function getapi() {
    return fetch(api_url)
        .then(function(res) { return res.json() })
        .then(function(data) {
            return data;
        }).then(function(articles) {
            return articles.articles;
        });
};

Then, I've created a function to store the data. This function would search for an information that is equal to the title and if it doesn't exist, then it will be stored into my database.

exports.pushData = functions.pubsub.schedule('every 2 hours').onRun((context) => {
    getapi().then(function(result) {

        var ref = database.ref('noticias');

        for (const res of result) {
            //result.forEach(function(result) {
            ref.orderByChild('title').equalTo(res.title).on('value', (snapshot) => {


                if (snapshot.exists()) {
                    console.log(res.title   " YA EXISTE EN LA BASE DE DATOS");

                } else {
                    console.log(res.title   " NO ESTÁ EN LA BASE DE DATOS");
                    database.ref('noticias/noticia'   contador   '/title').set(res.title);
                    database.ref('noticias/noticia'   contador   '/content').set(res.content);
                    database.ref('noticias/noticia'   contador   '/publishedAt').set(res.publishedAt);
                    database.ref('noticias/noticia'   contador   '/imgUrl').set(res.urlToImage);
                    contador = contador   1;
                }

            }, (errorObject) => {
                console.log('The read failed: '   errorObject.name);
            });

        };

    });
});

For the first insertion (when the database was empty), it worked perfect, but then, it started to create an infinite loop for the console.log. I think this might be because of the .on . It is listening for any change, so it can create an infinite loop. I think the solution would be to write .once instead, I'm not sure.

I've made another type function and I think this can work great, but I haven't tried it yet. I think that is is even more eficient. I am afraid to deploy it because, as you know, to use firebase functions I had to upgrade to blaze plan and this would charge me if I exceed the use.

exports.pushData = functions.pubsub.schedule('every 2 hours').onRun((context) => {
    getapi().then(function(result) {

        var ref = database.ref('noticias');

        result.forEach(function(res) {
            ref.orderByChild('title').equalTo(res.title).once('value', (snapshot) => {

                if (!snapshot.exists()) {
                    ref.push({
                        title: res.title,
                        content: res.content,
                        publishedAt: res.publishedAt,
                        urlToImage: res.urlToImage
                    });;
                }
            
             

            }, (errorObject) => {
                console.log('The read failed: '   errorObject.name);
            });

        });
    });
});

So, what do you think? Would this work?

CodePudding user response:

The problem in your first listener snippet is that you use on('value':

ref.orderByChild('title').equalTo(res.title).on('value',

This attaches a listener that immediately returns any child nodes with that specific title, and then continues to listen for any updates to that data. So if you write to one of the child nodes you get back, that will again trigger the same code, leading to the infinite loop you describe.

To fix this, you can either listen for on('child_added' or (better) use once or get to get the data once, instead of continuing to listen for update. Since your last snippet uses once it indeed should no longer cause the infinite loop that you had.

Instead of testing this on your actual, upgraded Firebase project, I recommend installing the local emulator suite, which allows you to test it quickly, locally, and at no cost.

  • Related