JavaScript中的对象数组未按预期返回

时间:2019-06-13 03:06:10

标签: javascript jquery arrays sqlite

我有一个函数,该函数返回Javascript中的对象列表,并且我正在从另一个函数中调用该函数,并尝试使用其中的某些值,但是每当我尝试访问所述值时,它们都会返回未定义状态。

这是我生成列表的函数-想法是,如果不存在,它将创建一个sqlite3数据库,并返回包含每个事件的数组。

function listAllEvents() {
    const sqlite3 = require('sqlite3').verbose();
    const db = new sqlite3.Database('schedule.db');

    const selectionArray = [];

    db.serialize(() => {
        db.run(`
        CREATE TABLE IF NOT EXISTS todo (
            name text,
            date text,
            id text primary key
            )
        `);

        db.all('SELECT * FROM todo ORDER BY date', [], (err, rows) => {
            if (err) {
                throw err;
            }

            rows.forEach((row) => {
                selectionArray.push(row);
            });
        });
    });
    return selectionArray;
}

我从另一个函数中调用了该函数,但是当我尝试从数组中访问值时,它们似乎无法正常工作,我无法弄清楚。

function displayUpcomingEvents() {
    const events = listAllEvents();

    // console.log(events); <-- This line here! In the console, it correctly states the length of the array
    // console.log(events.length) <-- This line, however, returns 0. Why?
    // console.log(events[0]) <-- This doesn't work either, it just returns "undefined".

    for (let i = 0; i < events.length; i += 1) {
        $('#upcomingEvents').after('<li>asdf</li>');
    }
}

例如,如果我要通过控制台在数据库中创建两个事件,

events is an Array(2) with indices
- 0: {name: "my_event", date: "2019-06-04", id: "c017c392d446d4b2"}
- 1: {name: "my_event_2", date: "2019-06-04", id: "6d655ac8dd02e3fd"},

events.length returns 0,
and events[0] returns undefined.

这是为什么,我该怎么解决?

2 个答案:

答案 0 :(得分:0)

发生这种情况的可能原因是由于JS的异步特性,这意味着在成功执行console.log函数之前,所有listAllEvents()语句都已被执行,

所以我的建议是尝试使用Promise,仅在该函数返回Promise时,执行listAllEvents()函数之后提到的所有操作。

您还可以尝试使函数异步,并使用await等待其成功执行。 (更明智的选择将是使用异步)

Link to ASYNC Functions and Usage Link to Promises

您还可以通过执行console.log(row)来检查答案的有效性,其中将行推入数组。您将观察到console.log(row)将在打印事件和其他日志语句之后最后执行。

答案 1 :(得分:0)

问题在于您的函数在设置值之前返回了变量。 db.serialize函数将异步运行(在程序的正常流程之外),而return语句将在此之后立即运行。您可以做的一件事是将异步/等待与Promise结合使用。在这种情况下,变量results将在继续下一行之前等待promise被解决。

async function listAllEvents() {    
    const selectionArray = [];

    let promise = new Promise( function (resolve, reject) {
        db.serialize(() => {
            db.run(
            CREATE TABLE IF NOT EXISTS todo (
            name text,
                date text,
                id text primary key
                )
            );

            db.all('SELECT * FROM todo ORDER BY date', [], (err, rows) => {
                if (err) {
                    // add code here to reject promise
                    throw err;
                }

                rows.forEach((row) => {
                    selectionArray.push(row);
                });
                resolve(selectionArray);// resolve the promise
            });
        });
    });

    let results = await promise;
    return results; 
};

async function displayUpcomingEvents() {
    const events = await listAllEvents();

    // console.log(events); <-- This line here! In the console, it correctly states the length of the array
    // console.log(events.length) <-- This line, however, returns 0. Why?
    // console.log(events[0]) <-- This doesn't work either, it just returns "undefined".

    for (let i = 0; i < events.length; i += 1) {
        $('#upcomingEvents').after('<li>asdf</li>');
    }
}

请注意,displayUpcomingEvents函数也将需要异步,否则您将无法使用await关键字。

Promise关键字MDN: Promise的其他阅读内容

异步/等待MDN: Asyn/Await的其他阅读内容