【问题标题】:How to hold a node api execution till a db query does not return null如何保持节点 api 执行直到数据库查询不返回 null
【发布时间】:2021-02-10 22:24:53
【问题描述】:

似乎对一段代码的不需要的要求,但就我而言,这正是我所需要的。我有一个与第三方服务交互的 api (API-1)。这个第三方服务不是直接给我一个可以转发回前端的响应,而是给我在 API-2 上的响应(使用 webhook 侦听器端点)。我正在保存通过收听数据库中的 webhook 获得的 API-2 响应。现在,我不知何故需要这个响应,它现在位于我的 API-1 中的数据库中,以便我可以将它转发回前端。如果我在 API-1 的流程中立即查询数据库(就在使用第三方服务 API 之后),我会得到 null,因为 API-2 正在使用 webhook 异步获取响应(主要是 1- 2 秒)。所以我需要找出一种简单的方法来等待/保持 API-1 流,直到数据库不返回 null/返回我从 API-2 保存在数据库中的响应。我不确定间隔是否总是 1-2 秒,因此我不能为此使用 setTimeout。

//API-1
const sendPaymentRequest = async (req, res) => {
  try {
    const payment_reponse = await axios.post(url, body, config);
    const { data } = payment_reponse;
    console.log("Payment request => ", data);

    //Check result i.e response from http listener
    const webhookResponse = await MpesaModel.findOne({
      conversationId: data.ConversationID
    });

    console.log('Webhook response => ', webhookResponse); //This is null

    res.status(200).json({ message: "Send money request", data });
  } catch (error) {
    console.log("Error while making a payment request", error);
    res
      .status(400)
      .json({ message: "Error while send payment request", error: error.data });
  }
};


//API-2 - This is the webhook which receives the response
const saveWebhookB2C = async (req, res) => {
  const { Result } = req.body;
  //console.log('Mpesa webhook data received => ', Result);

  let saveResponse = new MpesaModel({
    ...Result,
  });
  const result = await saveResponse.save();
  console.log('B2c mpesa to kenya saved in db => ', result);
  res.status(200).send();
};

【问题讨论】:

  • 写下你自己的承诺,直到你 saveResponse.save() 之前不要解决它 - 然后在 sendPaymentRequest() 中等待自定义响应 - 这样,你就可以控制解决的时间。

标签: javascript node.js mongodb api


【解决方案1】:

等到响应与 null 不同:

let webhookResponse = null;
while (response === null) {
  await sleep(1000);
  webhookResponse = await MpesaModel.findOne({
    conversationId: data.ConversationID,
  });
  
}

sleep 函数应该相当简单(我们只使用它等待一秒钟直到下一个查询):

const sleep = (timeInMilliseconds) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(), timeInMilliseconds);
  });
};

注意:如果答案始终为空,则 while 循环将永远运行,因此您可能希望在 while 中添加另一个条件以防结果始终为空(可能是最大尝试次数?)。

【讨论】:

  • 效果很好很高兴我学会了一种新的忍者技术
【解决方案2】:
async function getNotNullResponse({conversationId}){
    const webhookResponse = await MpesaModel.findOne({conversationId});
    return webhookResponse || getNotNullResponse({conversationId});
}

//API-1
const sendPaymentRequest = async (req, res) => {
  try {
    const payment_reponse = await axios.post(url, body, config);
    const { data } = payment_reponse;
    console.log("Payment request => ", data);

    //Check result i.e response from http listener
    const webhookResponse = await getNotNullResponse({
      conversationId: data.ConversationID
    });

    console.log('Webhook response => ', webhookResponse); //This is not null

    res.status(200).json({ message: "Send money request", data });
  } catch (error) {
    console.log("Error while making a payment request", error);
    res
      .status(400)
      .json({ message: "Error while send payment request", error: error.data });
  }
};


//API-2 - This is the webhook which receives the response
const saveWebhookB2C = async (req, res) => {
  const { Result } = req.body;
  //console.log('Mpesa webhook data received => ', Result);

  let saveResponse = new MpesaModel({
    ...Result,
  });
  const result = await saveResponse.save();
  console.log('B2c mpesa to kenya saved in db => ', result);
  res.status(200).send();
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多