Array declared outside the function and pushed elements in the function is considered empty array

Asked 2 years ago, Updated 2 years ago, 16 views

I am currently creating an application using indexedDB, and I wrote the following code to add objects retrieved using the cursor to the previously declared array, but it doesn't work the way I thought it would.

function myFunc(){
// Abbreviated
var columns = [ ];
index.openCursor(range).onscess=function(event){
    if(event.target.result==null){
        return;
    }
    varcursor=event.target.result;
    columns.push (cursor.value);
    cursor.continue();
};
return columns;
}

If you output this column value to the console, you will only see [] in the initial state, and if you select the parentheses, you will see

Array [0]
0—Object
1—Object

You will see the display.Also, each element contains exactly what you expect.
However, this array appears to be an overhead array, and if you print the return value of columns.toString() just before return columns;, you will get an empty string.

By the way, when I output the return value of columns.toString() inside if(event.target.result==null){}, the output is [objectObjectObject].

As I looked into it in my own way, I somehow understood that the scope of the array was probably related to this problem, but I couldn't think of how I could avoid it.

I would like to process and utilize this column further on the actual application, but columns[0] is undefined, so the loop is not available, and the columns.filter() process does not work as expected.

I would appreciate it if you could tell me why this phenomenon occurs and how to avoid it.

javascript

2022-09-29 21:58

2 Answers

It's not a scope problem, it's an asynchronous processing problem.The closure you are substituting for the onsuccess property function(event){...} does not run immediately, but registers only the closure immediately after the successful completion of the index.openCursor(range) request.In other words, columns is empty at that time, so your myFunc() function returns to an empty array.(Then a request will be made.)

A recent browser with indexedDB might be tempted to use Promise, but here's a pattern that uses classic callbacks for completion.

Your myFunc will be rewritten as follows:

function myFunc(onComplete){
    // Abbreviated
    var columns = [ ];
    index.openCursor(range).onscess=function(event){
        if(event.target.result==null){
            // Call back for completion after reading data to the end
            onComplete(columns);
            return;
        }
        varcursor=event.target.result;
        columns.push (cursor.value);
        cursor.continue();
    };
    // When control was transferred to this line, the closure given to onsuccess was not executed yet
    // return columns;
}

When calling, use the

varcols=myFunc();
Working with //cols...

Instead of obtaining results as a function return value as shown in , you pass the completion closure as an argument and receive the results within the closure as follows:

// Passes a closure (can be a function) for completion callback with one argument
myFunc(function(cols){
    Working with //cols...
});

I didn't have time to imagine and write all the preparations for opening the database, defining objects, pouring test data in…, so there might be a small mistake, but basically I should be able to write code to retrieve and use this idea.Try it.


2022-09-29 21:58

@With Le Pered'OO's advice, I was able to write something that behaves as expected using promotion.
I don't know if it's a desirable way to use it because I only understand that Promise is to wait for the asynchronous process to finish, but I'll leave it as an answer.

function myFunc(){
    // Abbreviated
    return new Promise (function(resolve, reject) {
        var columns = [ ];
        index.openCursor(range).onscess=function(event){
            if(event.target.result==null){
                resolve(columns);
                return;
            }
            varcursor=event.target.result;
            columns.push (cursor.value);
            cursor.continue();
        };
    });
}

Modify myFunc as shown in , and when calling it

myFunc().then(function(columns){
    // Write the action using "columns" here
    console.log (columns.toString()) ;// [object Object]
})

By doing so, we were able to successfully retrieve the array containing the objects.
For the time being, I was able to write something that works properly, but please let me know if there are any mistakes or "this should be done."


2022-09-29 21:58

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.