pg-promise解决map函数中的多个查询

时间:2020-06-25 00:05:14

标签: node.js postgresql pg-promise

pg-promise transaction with dependent queries in forEach loop gives warning Error: Querying against a released or lost connection相关,我现在正在尝试从地图函数中返回多个查询

const {db} = require('../db')

async function get(id) {
  return await db
    .task(async t => {
      const items = await t.any(`SELECT i.* FROM item i WHERE i.parent_id = $1#`, id)
      const itemDetails = items.map(async item => {
        const layers = await t.any(`SELECT l.* FROM layer l WHERE l.item_id = $1#`, item.id)
        const bases = await t.any(`SELECT b.* FROM base b WHERE b.item_id = $1#`, item.id)
        return [layers, bases]
      })
      // Not resolving properly!
      await t.batch(itemDetails.flat())

      return {items: items, itemDetails: itemDetails}
    })
    .then(data => {
      return {success: true, response: data}
    })
    .catch(error => {
      return {success: false, response: error.message || error}
    })
}

但是,我不确定如何正确解决多个查询(层和层)。如果我要返回一个或另一个,则根据链接的问题,我可以在继续之前批量解决承诺数组。但是,在每次地图迭代中返回多个查询时,我不确定在继续之前如何正确解决所有问题。

2 个答案:

答案 0 :(得分:0)

您正在做一些奇怪的事情。这是更正的版本:

function get(id) {
  return db.task(async t => {
      const items = await t.any(`SELECT i.* FROM item i WHERE i.parent_id = $<id>`, {id});
      const itemDetails = items.map(async item => {
        const layers = await t.any(`SELECT l.* FROM layer l WHERE l.item_id = $<id>`, item);
        const bases = await t.any(`SELECT b.* FROM base b WHERE b.item_id = $<id>`, item);
        return {layers, bases};
      });

      const details = await t.batch(itemDetails);

      return {items, details};
    })
    .then(data => {
      return {success: true, response: data};
    })
    .catch(error => {
      return {success: false, response: error.message || error};
    })
}

请注意,您在这里仍然会有一些顾虑,因为.then->.catch应该在此处的get函数之外,即避免将数据库逻辑与HTTP控制器混合。

答案 1 :(得分:0)

谢谢!因此,要完全分离关注点,我应该执行以下操作:

function get(id) {
  return db.task(async t => {
      const items = await t.any(`SELECT i.* FROM item i WHERE i.parent_id = $<id>`, {id});
      const itemDetails = items.map(async item => {
        const layers = await t.any(`SELECT l.* FROM layer l WHERE l.item_id = $<id>`, item);
        const bases = await t.any(`SELECT b.* FROM base b WHERE b.item_id = $<id>`, item);
        return {layers, bases};
      });

      const details = await t.batch(itemDetails);

      return {items, details};
    })

然后调用此函数时,说将其添加到express api中,请

  router.get('/:id', async (req, res, next) => {
    const all = await get(req.params.id)
      .then(data => {
        return {success: true, response: data}
      })
      .catch(error => {
        return {success: false, response: error.message || error}
      })
    res.json(all)
  })