gpt4 book ai didi

mysql - 取消嵌套 Node 数据库调用

转载 作者:行者123 更新时间:2023-12-03 12:12:00 25 4
gpt4 key购买 nike

我有一个普通

var express = require('express')
Node 表示 www 页面,像往常一样使用 session、pug 等。我的数据库调用
var db = require('./scripts/myHappyMysqlScript')
我很自然地使用 mysql , 所以在 db 脚本中
var mysql = require('mysql')
所以例如
app.get('/catPhotos', (req, response) => {
response.render('catPhotos.pug');
})
假设一个页面有一个表,显示了 petNames 数据库中的内容,
app.get('/pets', function(req, res, next) {
db.allPetNames(function(err, petsList) {
res.render('pets.pug',
{
'petsList': petsList,
'pretty' : true
})
})
到目前为止一切都很好。
但这里有一个案例 三 table 在 pug 页面上,以及三个不同的数据库调用:
db.cats(function(err, c) {
db.dogs(function(err, d) {
db.budgies(function(err, b) {
res.render('bigScreen.pug',
{
'cats' : c,
'k9s': d,
'budgies': b,
'pretty' : true
})
})
})
})
我只是这样嵌套它们。
这似乎工作得很好。
它正确地按顺序等待。错误发生并得到妥善处理,等等。
但是有没有更好的语法,更好的方法?
对于真正的™ Node 而非 Swift 程序员来说,Node Way 是什么?!
也许考虑到我正在使用 mysql图书馆,如果这是相关的。

请注意,总体而言,一种更好的方法是使用 Ajax 之类的东西在网页的每个“部分”中进行流式传输。事实上,我一直都在这样做。我在这里问的是,假设在 res.render 我确实想一次返回所有信息,有什么比这样嵌套更好的吗?干杯

最佳答案

您可以使用 promises 摆脱嵌套的数据库调用。 .
既然您提到您正在使用 mysql 用于与数据库交互的库,不幸的是,该库不提供基于 promise 的 API。因此,要摆脱代码中的嵌套数据库调用,您需要围绕数据库调用的回调版本创建一个基于 Promise 的包装器。
有关什么是 Promise 及其工作方式的一般概述,请参阅以下链接:

  • MDN - Promise .
  • MDN - Using Promises

  • 下面是一个示例,说明如何创建基于 Promise 的包装器,然后使用该包装器摆脱嵌套的数据库调用。
    这个基于 promise 的包装器只是一个返回 promise 的函数。它创建一个 promise 实例,包装底层数据库调用,最终当数据库调用返回数据时,它会通知您的代码。
    function getCats() {
    return new Promise((resolve, reject) => {
    // make the database call
    db.cats((error, cats) => {
    // in case of an error, reject the promise by
    // calling "reject" function
    // Also pass the "error" object to the "reject" function
    // as an argument to get access to the error message
    // in the code that calls this "getCats" function
    if (error) {
    reject(error);
    return;
    }

    // if there was no error, call "resolve" function
    // to resolve the promise. Promise will be resolved
    // in case of successful database call
    // Also pass the data to "resolve" function
    // to access this data in the code that calls this
    // "getCats" function
    resolve(cats);
    });
    });
    }
    现在在你的路由处理函数中,而不是调用 db.cats(...) , 调用 getCats包装函数。
    有两种方法可以调用返回 promise 的函数:
  • Promise-chaining (详情请访问上述链接)
  • async-await语法(推荐)

  • 以下代码示例使用 async-await句法。为此,首先将路由处理函数标记为 async通过使用 async function 之前的关键字关键词。这样做,我们可以使用 await此路由处理程序函数中的关键字。
    app.get('/pets', async function(req, res, next) {
    try {
    const cats = await getCats();
    // similar wrappers for other database calls
    const dogs = await getDogs();
    const budgies = await getBudgies();

    // render the pub template, passing in the data
    // fetched from the database
    ...

    catch (error) {
    // catch block will be invoked if the promise returned by
    // the promise-based wrapper function is rejected
    // handle the error appropriately
    }
    });
    上面的代码示例只展示了如何包装 db.cats(...) database 在基于 promise 的包装器中调用并使用该包装器从数据库中获取数据。同样,您可以为 db.dogs(...) 创建包装器。和 db.budgies(...)调用。
    而不是为每个数据库调用创建一个单独的基于 promise 的包装器,理想情况下, 你应该创建一个可重用的基于 promise 的包装函数 它接受一个函数来调用并将该函数调用包装在一个 promise 中,就像上面的代码示例中所示,即 getCats功能。
    并行数据库调用
    在路由处理函数中的上述代码中需要注意的一件重要事情
    const cats = await getCats();
    const dogs = await getDogs();
    const budgies = await getBudgies();
    是这会导致 顺序数据库调用 这可能是您想要的,也可能不是。
    如果这些数据库调用不相互依赖,那么您可以使用 Promise.all() 并行调用基于 promise 的包装器方法。
    以下代码示例显示了如何使用 Promise.all() 并行调用基于 Promise 的包装器函数.
    app.get('/pets', async function(req, res, next) {
    try {
    // "petsData" will be an array that will contain all the data from
    // three database calls.
    const petsData = await Promise.all([getCats(), getDogs(), getBudgies()]);

    // render the pub template, passing in the data
    // fetched from the database
    ...

    catch (error) {
    ...
    }
    });
    我希望这足以帮助您摆脱当前代码中的嵌套数据库调用,并开始在代码中使用 promise。

    关于mysql - 取消嵌套 Node 数据库调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64464555/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com