当前位置: 首页 > 面试题库 >

使用Node.js同步数据库查询

柳英豪
2023-03-14
问题内容

我有一个Node.js /
Express应用程序,该应用程序查询路由内的MySQL数据库,并将结果显示给用户。我的问题是如何在将用户重定向到他们请求的页面之前运行查询并阻止直到两个查询都完成?

在我的示例中,我有2个查询需要在呈现页面之前完成。如果将查询2嵌套在查询1的“结果”回调中,则可以使查询同步运行。但是,当查询数量增加时,这将变得非常复杂。

如何在不将后续查询嵌套在先前查询的“结果”回调中的情况下同步运行多个(在本例中为2个)数据库查询?

我已经查看了Node模块中的“流控制/异步好东西”,并尝试了flow-js,但我无法使其与异步查询一起使用。

下面列出的是我尝试从“ / home”路由执行的2个查询。Node专家可以解释这样做的“正确”方法吗?

app.get('/home', function (req,res) {
    var user_array = [];
    var title_array = [];

    // first query
    var sql = 'select user_name from users';
    db.execute(sql)
        .addListener('row', function(r) {
            user_array.push( { user_name: r.user_name } );
        })
        .addListener('result', function(r) {
            req.session.user_array = user_array;
        });

    // second query
    var sql = 'select title from code_samples';
    db.execute(sql)
        .addListener('row', function(r) {
            title_array.push( { title: r.title } );
        })
        .addListener('result', function(r) {
            req.session.title_array = title_array;
        });

        // because the queries are async no data is returned to the user
        res.render('home.ejs', {layout: false, locals: { user_name: user_array, title: title_array }});
});

问题答案:

节点的目的不是在乎事情发生的顺序。这会使某些情况变得复杂。嵌套回调没有可耻之处。一旦习惯了它的外观,您可能会发现自己实际上更喜欢这种样式。我做;
很清楚将触发什么顺序的回调。如果需要的话,可以放弃匿名函数以使其不再那么冗长。

如果您愿意稍微重构代码,则可以使用“典型”嵌套回调方法。如果您想避免回调,可以使用许多异步框架来尝试并帮助您做到这一点。您可能要检查的一种是async.js(https://github.com/fjakobs/async.js)。每个示例:

app.get('/home', function (req,res) {
    var lock = 2;
    var result = {};
    result.user_array = [];
    result.title_array = [];

    var finishRequest = function(result) {
        req.session.title_array = result.title_array;
        req.session.user_array = result.user_array;
        res.render('home.ejs', {layout: false, locals: { user_name: result.user_array, title: result.title_array }});
    };

    // first query
    var q1 = function(fn) {
      var sql = 'select user_name from users';
      db.execute(sql)
          .addListener('row', function(r) {
              result.user_array.push( { user_name: r.user_name } );
          })
          .addListener('result', function(r) {
              return fn && fn(null, result);
        });
    };

    // second query
    var q2 = function(fn) {
      var sql = 'select title from code_samples';
      db.execute(sql)
          .addListener('row', function(r) {
              result.title_array.push( { title: r.title } );
          })
          .addListener('result', function(r) {
              return fn && fn(null, result);
          });
    }

    //Standard nested callbacks
    q1(function (err, result) {
      if (err) { return; //do something}

      q2(function (err, result) {
        if (err) { return; //do something}

        finishRequest(result);
      });
    });

    //Using async.js
    async.list([
        q1,
        q2,
    ]).call().end(function(err, result) {
      finishRequest(result);
    });

});

一次性,我可能只使用引用计数类型方法。只需跟踪要执行的查询数量,并在查询全部完成后呈现响应即可。

app.get('/home', function (req,res) {
    var lock = 2;
    var user_array = [];
    var title_array = [];

    var finishRequest = function() {
        res.render('home.ejs', {layout: false, locals: { user_name: user_array, title: title_array }});
    }

    // first query
    var sql = 'select user_name from users';
    db.execute(sql)
        .addListener('row', function(r) {
            user_array.push( { user_name: r.user_name } );
        })
        .addListener('result', function(r) {
            req.session.user_array = user_array;
            lock -= 1;

            if (lock === 0) {
              finishRequest();
            }
        });

    // second query
    var sql = 'select title from code_samples';
    db.execute(sql)
        .addListener('row', function(r) {
            title_array.push( { title: r.title } );
        })
        .addListener('result', function(r) {
            req.session.title_array = title_array;
            lock -= 1;

            if (lock === 0) {
              finishRequest();
            }
        });
});

更好的方法是在呈现响应之前,在每个“结果”回调中简单地调用finishRequest()以检查非空数组。在您的情况下是否可行取决于您的要求。



 类似资料:
  • 问题内容: 我是nodejs的新手,正在编写一些查询MySQL数据库并从给定的user_id返回用户名的代码。我一直在阅读,您所有的功能都应该是异步的。在这种情况下,理想情况下,我希望服务器能够在进行此查询时响应其他事件请求。但是,这不是一个特别大的查询,只返回一个值。也许我应该使其同步?(如果这是您的答案,那么更改示例代码将是不错的选择)无论如何,这是我的功能。它在最后一行“ return cu

  • “同步到数据库”功能让你比对物理模型和现有数据库或模式,显示它们之间结构的差异,并提供同步模型的结构到目标连接。 Navicat 提供一个向导,一步一步指导你完成任务: 选择“文件”->“同步到数据库”。 选择源数据库、模式,然后从现有的连接中选择目标连接、数据库、模式。 点击“选项”并选择比对或高级选项。 点击“比对”以显示源对象和目标对象之间的差异。 选择要同步的对象。 点击“部署”以生成一组

  • “同步到数据库”功能让你比对模型和现有数据库或模式,显示它们之间结构的差异,并提供同步模型的结构到目标连接。 Navicat 提供一个向导,一步一步指导你完成任务: 选择“文件”->“同步到数据库”。 选择源数据库、模式,然后从现有的连接中选择目标连接、数据库、模式。 点击“选项”并选择比对或高级选项。 点击“比对”以显示源对象和目标对象之间的差异。 选择要同步的对象。 点击“部署”以生成一组脚本

  • “同步到数据库”功能让你比对物理模型和现有数据库或模式,显示它们之间结构的差异,并提供同步模型的结构到目标连接。 Navicat 提供一个向导,一步一步指导你完成任务: 选择“文件”->“同步到数据库”。 选择源数据库、模式,然后从现有的连接中选择目标连接、数据库、模式。 点击“选项”并选择比对或高级选项。 点击“比对”以显示源对象和目标对象之间的差异。 选择要同步的对象。 点击“部署”以生成一组

  • 同步能够部分智能的根据结构体的变动检测表结构的变动,并自动同步。目前有两个实现: Sync Sync将进行如下的同步操作: * 自动检测和创建表,这个检测是根据表的名字 * 自动检测和新增表中的字段,这个检测是根据字段名 * 自动检测和创建索引和唯一索引,这个检测是根据索引的一个或多个字段名,而不根据索引名称 调用方法如下: err := engine.Sync(new(User), ne

  • 我正在尝试使用基于Kafka Connect的Confluent在几个MySQL数据库之间同步数据。我在源连接器配置中使用了“批量”作为模式,因为主键类型是 varchar,所以我无法使用递增模式。它工作正常,但我遇到了两个问题: 似乎它无法同步删除,当源数据库中的数据被删除时,接收器数据库没有任何变化。数据仍存在于接收器数据库中。 同步数据需要相当长的时间。就我而言,同步具有 2~4k 行的表大