无法读取未定义的属性(读取 'fitness')

Cannot read properties of undefined (reading 'fitness')

我们目前正在为我们的室友配对项目制作一个网站。我们正处于制作结果页面的阶段,该页面应根据算法计算其兼容性百分比的一些问题显示 3 个最兼容的室友。

我们现在正尝试传递名为“fitness”的对象,该对象包含所有结果,即:

let fit = {
    fitness: Math.round(sum * 100),
    email: resident[i].email,
    name: resident[i].firstName + " " + resident[i].lastName,
};

到我们名为 results.ejs 的 .ejs 文件。 fit 对象被推入我们的全局“fitness”变量。

这是我们的 post 请求:

router.post("/results", function (request, response) {
    let item = request.body;
    let applicant_name = request.body.firstName;

    client.connect(function (err) {
        const db = client.db("myFirstDatabase");
        assert.equal(null, err);
        db.collection("residents").insertOne(item, function (err, result) {
            assert.equal(null, err);
            console.log("Item inserted");
        });
    });

    client.connect(function (err) {
        const db = client.db("myFirstDatabase");
        assert.equal(null, err);
        db.collection("residents")
            .find({})
            .toArray(function (err, resident) {
                if (err) throw err;

                /* weighting(request); */
                compatability(request, resident);
            });
    });

    client.close();
    response.render("pages/results", {
        applicant_name: applicant_name,
        resident: fitness,
    });
});

在我们的 results.ejs 文件中,我们使用 Bootstrap 卡片来显示 3 个最合适的室友。这是我们在 results.ejs 文件中使用的代码:

<p class="card-text">
    Compatibility %: <%= resident[0].fitness %><br />
    Name: <%= resident[0].name %> <br />
    Email: <%= resident[0].email %><br />
    Location: <br />
</p>

每当我们运行 post 请求时,我们都会收到一条错误消息“无法读取未定义的属性(读取'fitness')”,但是如果我们再次刷新,Node.js 服务器崩溃,但它显示了我们想要获得的实际值。如果我们加一个“?”在“resident[0]”之后,运行页面没有任何错误,但不显示来自对象的任何信息。 我们尝试了很多事情,但找不到解决此问题的正确方法。 提前致谢。

编辑

来自 .ejs 文件和我们的服务器端代码的完整代码,以及它在网站上的外观照片:https://pastebin.com/zRxdk6aq

本例中的错误"Cannot read properties of undefined (reading 'fitness')"表示resident[0]未定义。这可能是由于 resident 未定义或者是一个空数组(长度为 0)。

从您提供的代码中我看不到,您实际将对象推入全局 fitness 变量的位置或定义变量的位置。也许这就是问题所在。为了进一步帮助您,如果您能 post 代码肯定会有所帮助。

编辑: 查看您在 pastebin 中提供的新代码,看起来您正在使用异步函数,但期待同步行为。您当前的代码基本上如下所示:

router.post("/results", function (request, response) {
    client.connect(function (err) {
        // Insert data into db
    });

    client.connect(function (err) {
        // Fetch data from db
    });

    client.close();
    response.render("pages/results", {
        applicant_name: applicant_name,
        resident: fitness,
    });
});

问题在于,您的程序不会等待 DB-operations 完成后再呈现您的页面。这是因为 callback functions work.

我假设您正在使用 nodejs 的 mongoDB 驱动程序。除了经典的回调选项,它还允许使用 async/await:

router.post("/results", async (request, response) {
    // 

    await client.connect();

    const db = client.db('myFirstDatabase');
    await db.collection("residents").insertOne(request.body);

    let residents = await db.collection("residents").find({}).toArray();

    let fitness = compatability(request, resident);

    client.close();
    response.render("pages/results", {
        applicant_name: request.body.firstName,
        resident: fitness,
    });
});

function compatability(request, resident) {
    let fitness = [];
    // Do your calculations here
    return fitness;
}

这样您的请求处理程序就会一直等待,直到您将新项目插入数据库并获取现有项目。只有在那之后,它才会呈现您的页面,从而确保 fitness 变量已经填充了数据。

请注意,在此示例中,我还建议更改您的兼容性函数,以便它 returns 您的“适合度”变量,而不是使其成为全局变量。

如果您不熟悉 async/await,我建议您也尝试了解 Promises