pg-promise - 不解析多个查询

问题描述 投票:0回答:1

我正在创建一个群发邮件程序,允许公司向包含X订阅者数量的特定计划发送电子邮件模板。

但是,当使用pg-promise时,我无法想象如何遍历包含一个或多个唯一计划名称的数组,这些名称随后将用作后续查询的查询参数以收集单个结果数组。在express发回指定的错误消息之前,后续查询无法解析。

例如:

const selectedTemplate = await db.oneOrNone("SELECT * FROM templates WHERE userid=$1 and uniqueTemplateName=$2", [req.session.id, req.body.uniquetemplatename])

返回一个JSON对象......

{ ...
  plans : [ 'Unique Plan 1', 'Unique Plan 2', 'Unique Plan 3'...],
  ...
}

然后我想循环通过这个plans数组来收集一些订阅者电子邮件。由于selectedTemplate的plans数组可以包含单个“唯一计划”或多个,我试图找出如何使这个查询工作:

let subscriberEmails = [];

await each(selectedTemplate.plans, async plan => {
  const emails = await db.any("SELECT email FROM subscribers WHERE userid=$1 AND planName=$2", [req.session.id, plan])          
  each(emails, ({email}) => subscriberEmails.push(email))           
  console.log('Found emails: ', subscriberEmails);
})

console.log('Selected emails: ', subscriberEmails);
res.status(500).json({ message: "Route not configured yet" })

我遇到的问题是Express并没有等待pg-promise解决。所以它触发了我的500服务器“尚未配置路由”消息,然后解析查询:

14:48:33 SELECT * FROM templates WHERE userid='12345' and uniqueTemplateName='example-unique-template'

        selectedTemplate: anonymous {
          id: '84efa448-b149-11e8-a7fd-3b9e4e9e5ece',
          key: 9,
          userid: '12345',
          status: 'active',
          fromsender: '[email protected]',
          subject: 'Thank you for using our services!',
          templatename: 'Example Unique Template',
          uniquetemplatename: 'example-unique-template',
          message: '<h3>This is a test!</h3>',
          plans: [ 'Unique Plan 1', 'Unique Plan 2' ] 
        }

        Selected emails: []

POST /api/messages/create 500 28 - 34.125 ms

14:48:33 SELECT email FROM subscribers WHERE userid='12345' AND planName='Unique Plan 1'

        Found emails:  [ 
         '[email protected]',
         '[email protected]',
         '[email protected]'
        ]

14:48:34 SELECT email FROM subscribers WHERE userid='12345' AND planName='Unique Plan 2'

        Found emails:  [ 
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]',
         '[email protected]' 
        ]

功能如下:

async (req, res, done) => {
    if (!req.body) {
      return res.status(404).json({ message: "Missing query parameters" });
      done();
    }

    try {
      const selectedTemplate = await db.oneOrNone("SELECT * FROM templates WHERE userid=$1 and uniqueTemplateName=$2", [req.session.id, uniquetemplatename]);
      if (!selectedTemplate) {
        return res.status(404).json({ message: "Unable to locate selected template" });
        done();
      }
      console.log('selectedTemplate', selectedTemplate);

      let subscriberEmails = [];
      await each(selectedTemplate.plans, async plan => {
        const emails = await db.any("SELECT email FROM subscribers WHERE userid=$1 AND planName=$2", [req.session.id, plan])
        each(emails, ({email}) => subscriberEmails.push(email))
        console.log('Found emails: ', subscriberEmails);
      })

      console.log('Selected emails: ', subscriberEmails); 
      res.status(500).json({ message: "Route not configured yet" })
    } catch (err) { res.status(500).json({ message: err }); done(); }
  }

一个非常简化的数据库结构:

├── Template
│   └── Plans (references an array of unique plan name(s))
|
|── Plan
|   └── PlanName (unique plan name)
|
│── Subscriber
|   └── PlanName (references a single unique plan name)
|   └── Email (unique email)

我尝试过使用db.task(),但同样,在Express发回消息之前,查询没有解决。

postgresql express pg-promise
1个回答
1
投票

找出问题所在。以防万一其他人偶然发现这种困境:像“map”和“each”这样的函数不处理async / await。他们只是返回一个待定的Promise。因此,您将需要使用像Bluebird这样的库,它实现基于Promise的每个/ map / etc函数(位于“Collections”下)。

以上工作的修复工作:

try {
  await db.task('create-message', async t => {
    const selectedTemplate = await t.oneOrNone(findTemplateByName, [req.session.id, uniquetemplatename])
    if (!selectedTemplate) return sendError(unableToLocate('template'), res, done);
    const { fromsender, subject, message, plans, templatename } = selectedTemplate;

    let subscriberEmails = [];
    await Promise.each(plans, async plan => {
        const emails = await t.any(getAllEmailsByPlan, [req.session.id, plan]);
        each(emails, ({email}) => subscriberEmails.push(email));
    })

    if (isEmpty(subscriberEmails)) return sendError(unableToLocate('subscribers in the selected plan(s)'), res, done);

    const msg = {
        to: subscriberEmails,
        from: fromsender,
        replyTo: fromsender,
        subject: subject,
        html: message
    };

    await mailer.sendMultiple(msg);

    await t.none(createMessageTransaction, [req.session.id, templatename, fromsender, subject, currentDate, plans]);

    await t.none(createNotification, [req.session.id, 'mail_outline', `The following template: ${templatename} has been sent out to the subscibers in the following ${plans.length > 1 ? "plans" : "plan"}: ${plans}.`, date]);

    return res.status(201).send(null);
  })
} catch (err) { return sendError(err, res, done); }  
© www.soinside.com 2019 - 2024. All rights reserved.