Home > Software engineering >  Two firebase get() inside each other makes the global variable becomes null and can only handle the
Two firebase get() inside each other makes the global variable becomes null and can only handle the

Time:02-04

I have a firebase database that looks like this: Inside 'canvas' collection, there are many data as well.

Now, what I need is to retrieve every document inside 'canvas', including their name field. So, what I did is retrieving the document's name, and from that, I retrieve canvas documents of every single documents.

function getDatabase() {
    let rowId = 0;
    dbRef.get().then((querySnapshot) => {
        querySnapshot.forEach((doc) => {

            // HTML for each row
            let $idEmo = $("<th>", { "scope": "row" });
            let $canvasEmo = $("<th>");
            let $nameEmo = $("<th>");
            let $dateEmo = $("<th>");
            let $canvasEmoContent = $("<canvas>")
            $canvasEmoContent.attr({
                width: "100",
                height: "100",
                id: "db-canvas-"   rowId
            });

            // Prepend data into one row
            $idEmo.prepend(rowId);
            $canvasEmo.prepend($canvasEmoContent);
            $nameEmo.prepend(doc.data().name);
            $dateEmo.prepend(doc.data().date);

            let $tableRow = $("<tr>");
            $tableRow.addClass("t-row");
            $tableRow.prepend($idEmo, $canvasEmo, $nameEmo, $dateEmo);
            $("#emoji-table-body").append($tableRow);

            // Get the circles from the database in each row
            let dbCircle = R.clone(circleTemplate);
            dbRef.doc(doc.data().name).collection("canvas").get()
                .then((querySnapshot) => {
                    querySnapshot.forEach((bit) => {
                        let i = 8 * bit.data().posY   bit.data().posX;
                        dbCircle[i].posX = bit.data().posX;
                        dbCircle[i].posY = bit.data().posY;
                        dbCircle[i].isOn = bit.data().isOn;
                        dbCircle[i].color = bit.data().color;
                    });
                })
                .then(() => {
                    
                    makeDatabaseCanvas("db-canvas-"   rowId, dbCircle)
                    console.log(dbCircle)
                    console.log(dbCircle[3].isOn)
                    console.log(rowId)
                    rowId  ;
                })
            
        });
    });
}

Other functions:

    function makeDatabaseCanvas(id, dCircle) {
    renderBoard(id, 100);
    for (let i = 0; i < 64; i  ) {
        renderCircle(id, dCircle[i].posX, dCircle[i].posY, dCircle[i].isOn, dCircle[i].color, 4);
    }
}

    function renderBoard(id, size) {
    let context = document.getElementById(id).getContext('2d');
    context.fillStyle = '#000000';
    context.fillRect(0, 0, size, size);
}

// Circle rendering
function renderCircle(id, row, column, isOn, color, scale) {
    let context = document.getElementById(id).getContext('2d');
    let centerX = (row * 50   25) / scale;
    let centerY = (column * 50   25) / scale;
    let radius = 20 / scale;

    context.beginPath();
    context.arc(centerX, centerY, radius, 0, Math.PI * 2, true);
    context.fillStyle = ((isOn) ? color : '#FFFFFF');
    context.fill();
    context.stroke();
}

The problem with this is: for the second Foreach and onward, the variable rowId just... disappears. Everything is fine for the first Foreach (the makeDatabaseCanvas method works perfectly), but for the 2nd one, and onward, the console return the rowId is null. Here is the error returned.

The first foreach is fine, but the 2nd one has problems. The 'getContext' should receive the rowId

At this point, I have tried many solutions. I tried async/await but Foreach expects a synchronous function. I tried replacing it with For loop and... it returned nothing. I tried to put the name of the document inside an array and use async/await on it, but it also failed.

Thank you in advance.

EDIT: The error comes from the code to get the canvas id from the rowId (because I link them together for easier coding). Since it cannot access rowId, it cannot access the canvas id as well. I have editted the codes a bit to make them easier to be shown on Stackoverflow. So the whole codes are like that.

The codes outside of the scope still works. They are used to create a row with canvas tag. The problem codes are used to draw on the canvas

And as you can see in the picture, the first one is drawn perfectly. However, the second one cannot be drawn. The id does not increase, and the id of the 2nd canvas is 'db-canvas-0' where it should be 1.

CodePudding user response:

Change this line of code:

dbRef.doc(doc.data().name).collection("canvas").get()

to

dbRef.doc(doc.id).collection("canvas").get()

You should reference the document itself rather than referencing on the document's data object.

You could also check the code that I wrote which also gets data from the collection, documents and its subcollection.

dbRef = db.collection("collection");

let  rowId = 0;

    dbRef.get().then((querySnapshot) => {
      querySnapshot.forEach((document) => {
        document.ref.collection("sub_collection").get().then((querySnapshot) => {
            //Prepend Row HTML Data.
            console.log(['main_collection_data: ', rowId, document.data()]);
            rowId  ;
            querySnapshot.forEach((document) => {
                // Get the circles from the database in each row
                console.log(['sub_collection_data:', document.data()]);
            });
        })
      })
    });
  •  Tags:  
  • Related