使用Promise的同步数据库查询

时间:2019-07-31 02:23:27

标签: node.js promise async-await

很抱歉,如果我错过了一些琐碎的事情。 我想做的是同步调用数据库查询。在进行下一步之前,我需要确保数据库插入已完成。我也不想嵌套在回调中。 我正在尝试使用Promise,但它似乎没有按我预期的那样工作。 这是我的代码:

async init()
{
        await this.initWalletTable();
}


async initWalletTable()
{
   console.log("Creating wallet table");
   var self = this;
   walletParams.wallets.forEach(function(wallet) {

   (async() => {
         await self.insertWallet(wallet); 
         console.log("inserted " + wallet.multisig_wallet_name);
         })();
      });
 }


 insertWallet(wallet)
 {
      console.log("Inserting wallet " + wallet.multisig_wallet_name);
      return new Promise((resolve, reject) => {

            pool.query(`INSERT INTO ${schema}wallet \
                        (name, wallet_name_1, ) \
                        VALUES ($1, $2) \
                        ON CONFLICT (name) DO NOTHING`, [wallet.multisig_wallet_name, wallet.wallet_name1])
            .then(dbres => {
                return resolve(true);
            })
            .catch(e => {
                console.error(e.stack);
               return  resolve(true);
            })

        });
    }

2 个答案:

答案 0 :(得分:1)

我认为我在下面列出的解决方案可以解决您的问题。

  

我想要做的是同步调用数据库查询。在进行下一步之前,我需要确保数据库插入已完成。我也不想嵌套在回调中。

我不确定您要问什么。我想我知道您的意思,并且试图解决您的问题,但是如果我不理解您的意图,请告诉我。需要澄清的几点:

  • 承诺旨在使异步代码更易于维护和理解(而不是嵌套函数)。
  • async / await在此基础上构建,使您可以轻松编写同步的外观代码
  • 此异步外观代码仍在幕后使用promise,在幕后使用回调。
  • 您希望您的方法是异步的,尤其是因为这是数据库io。

您要让异步代码以系列的方式运行,而不是同时运行。

所做的更改

  • insertWallet方法中,由于pool.query()已经返回了承诺,因此您无需将其包装在显式承诺中。
  • 我不确定为什么将异步匿名函数包装在initWalletTable()内的立即调用函数表达式中,但是我认为如果删除该块会很好。

代码

class Wallet {
  constructor(walletParams) {
    this.walletParams = walletParams;
    this.initialized = this.init();
  }

  async init() {
    return await this.initWalletTable();
  }

  async initWalletTable() {
    console.log("Creating wallet table");
    this.walletParams.wallets.forEach((wallet) => {
      await this.insertWallet(wallet);
      console.log("inserted " + wallet.multisig_wallet_name);
    });
  }

  async insertWallet(wallet) {
    console.log("Inserting wallet " + wallet.multisig_wallet_name);
    return pool.query(`INSERT INTO ${schema}wallet \
                        (name, wallet_name_1, ) \
                        VALUES ($1, $2) \
                        ON CONFLICT (name) DO NOTHING`, [wallet.multisig_wallet_name, wallet.wallet_name1])
      .catch(e => {
        console.error(e.stack);
        throw e; // re-raise error
      });
  }
}

答案 1 :(得分:1)

您现有的代码有很多问题:

  1. 您无法使用Javascript将异步数据库调用转换为同步操作。不能做如果您真正想做的是对多个操作进行“排序”,那么第二个操作在第一个操作完成后进行,则可以轻松完成。

  2. .forEach()循环不等待await。您可以改用常规的for循环。

  3. 其中仅包含一个async的{​​{1}} IIFE并没有真正有用的作用。 IIFE仍会立即返回(不等待await)。

  4. 请记住,await函数在遇到第一个async时会立即返回promise。它不等待异步操作完成才返回。

  5. 您永远不想将现有的承诺包装在手动创建的await中。取而代之的是,您只返回已经拥有的承诺。

  6. 此代码中需要一个错误处理策略。现在,您的代码似乎试图忽略错误。那真的是正确的策略吗?

您可以改为:

new Promise()