【问题标题】:How to run a query only when another has completed with express js如何仅在另一个使用 express js 完成时运行查询
【发布时间】:2020-06-25 18:49:53
【问题描述】:

请对我温柔一点,我是 node js 的新手。我在 for 循环中运行两个查询,将值插入到两个名为 orders 和 requests 的表中。在插入订单表后,我将 insertId 传递给变量 orderid,然后将其添加到我的第二个插入查询中。所有这些工作正常,完成后我想查询一个名为 invoice 的视图,以便我可以获得一些我刚刚放入数据库的信息。问题是它甚至在完成两个查询之前就从视图返回结果,因此我得到一个空响应。这是我的代码。

for(var i = 0; i<items.length; i++){
  connection.query('INSERT INTO orders(referenceid,itemid,quantity,dac,requestid,locationid) VALUES(?,?,?,?,?,?);',[referenceid,items[i].id,items[i].quantity,dac,requestid,locationid], function(errors,results,fields){
                if(errors){ throw errors};
                    var orderid = results.insertId;
                connection.query('INSERT INTO requests(requestid,orderid,price) VALUES(?,?,?)',[requestid,orderid,price],function(errors,results,fields){
                })
  })

}
connection.query('SELECT * FROM invoice WHERE requestid = ? ,[requestid],function(errors,results,fields){
                })

所以任何人都可以帮助我让 SELECT 查询仅在 for 循环中的所有插入都完成时运行。我的数据库是mysql。

【问题讨论】:

    标签: mysql node.js express asynchronous async-await


    【解决方案1】:

    我不确定您使用的是哪个 SQL npm 模块,因此我无法参考任何文档,但我相信您对 connection.query() 的调用是异步的,因为它们应该是异步的。这会导致您在 for 循环外的最终 connection.query() 在 for 循环内的那些之前执行,因此,您将没有 requestId 可在最终查询中使用。

    我可以立即提供两种可能的解决方案:

    • 将查询调用嵌套到回调中
    • 使用明确的承诺

    因此,对于第一个选项,您可以将最终查询放入查询的嵌套回调中,放入 requests 表中。据我了解,您只希望在插入到ordersrequests 完成后从invoice 中选择行。

    至于第二个选项,您可以将 for 循环的内容重构为辅助函数,并将其封装为 return new Promise(),如下所示:

    const helper = (<any_params_you_need>) => {
       return new Promise(resolve, reject) => {
          for(var i = 0; i<items.length; i++){
             connection.query('INSERT INTO orders(referenceid,itemid,quantity,dac,requestid,locationid) VALUES(?,?,?,?,?,?);',[referenceid,items[i].id,items[i].quantity,dac,requestid,locationid], function(errors,results,fields){
                    if(errors) { reject(err); }
                    var orderid = results.insertId;
                    connection.query('INSERT INTO requests(requestid,orderid,price) 
                    VALUES(?,?,?)', 
                    [requestid,orderid,price],function(errors,results,fields){
                        resolve(results);
                    })
             })
          }
       }
    }
    

    一旦你设置了帮助函数,你就可以在你的选择查询之前使用await 像这样调用它:await helper();。例如,在调用函数中,它看起来像:

    ...
    const results = await helper();
    connection.query('SELECT * FROM invoice WHERE requestid = ? ,[requestid],function(errors,results,fields){});
    ...
    

    【讨论】:

    • 我不能使用嵌套回调,因为它是一个 for 循环,因此每次运行 for 循环时都会调用视图,但我希望它只在 for 循环运行时运行完毕。对于您的第二个解决方案,我仍然是节点的新手,所以如果您可以使用我的代码编写它,我将非常感激。因为我不知道 for 循环是否应该进入新的承诺,或者对发票视图的最终查询是否应该在那里。所以如果你能用我的代码来写的话。
    • 哦,那么第二种解决方案可能是要使用的解决方案。我已经用您现有的一些代码 b/c 更新了答案,发表评论太长了。请注意,在 Promise 中,您可以 resolve 该 Promise 使用您希望从 Promise 返回的任何值。有关承诺的更多信息,您可以查看此链接:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    猜你喜欢
    • 2019-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多