NodeJS 如何处理嵌套的 try/catch 机制

huangapple go评论67阅读模式
英文:

NodeJS how to handle nested try/catch mechanism

问题

I'm new to Node.js and I'm trying to code two nested try/catch and put retry logic for it. So when inner try/catch catches error I want it to send to outer catch and inside of it I will increase retry count by 1. So when it comes to 5 I will return from while loop. But my problem is that when inner try/catch throws an exception it is not caught by outer one. How can I make sure that it catches the error?

    try {
      channel.assertQueue(name, { durable: true, arguments: { "x-queue-type": "quorum" } }, async (error, queue) => {
        if (error)
          throw error;

        if (queue) {
          try {
            channel.sendToQueue(name, Buffer.from(message));
          } catch (e) {
            console.log(e);
            throw e;
          }
        }
      });
    } catch (e) {
      //retry count will be increased.
      throw e.message;
    }
英文:

I'm new to Node.js and I'm trying to code two nested try/catch and put retry logic for it. So when inner try/catch catches error I want it to send to outer catch and inside of it I will increase retry count by 1. So when it comes to 5 I will return from while loop. But my problem is that when inner try/catch throws an exception it is not caught by outer one. How can I make sure that it catches the error?

    try {
      channel.assertQueue(name, { durable: true, arguments: { "x-queue-type": "quorum" } }, async (error, queue) => {
        if (error)
          throw error;

        if (queue) {
          try {
            channel.sendToQueue(name, Buffer.from(message));
          } catch (e) {
            console.log(e);
            throw e;
          }
        }
      });
    } catch (e) {
      //retry count will be increased.
      throw e.message;
    }

答案1

得分: 1

确保外部的catch块捕获内部try/catch块中抛出的错误您可以按以下方式修改您的代码

    let retryCount = 0;
    
    async function attemptToSendMessage() {
      while (retryCount < 5) {
        try {
          await new Promise((resolve, reject) => {
            channel.assertQueue(
              name,
              { durable: true, arguments: { "x-queue-type": "quorum" } },
              async (error, queue) => {
                if (error) {
                  reject(error); // 如果发生错误,则拒绝承诺
                  return;
                }
    
                if (queue) {
                  try {
                    channel.sendToQueue(name, Buffer.from(message));
                    resolve(); // 如果消息成功发送,则解析承诺
                  } catch (e) {
                    reject(e); // 如果在发送消息时发生错误,则拒绝承诺
                  }
                }
              }
            );
          });
          break; // 如果消息成功发送,则退出while循环
        } catch (e) {
          console.log(e);
          retryCount++; // 增加重试计数
        }
      }
    
      if (retryCount === 5) {
        throw new Error("在5次尝试后未能发送消息。");
      }
    }
    
    // 用法
    try {
      await attemptToSendMessage();
    } catch (e) {
      // 在此处理错误
      console.log(e.message);
    }
英文:

To ensure that the outer catch block catches the error thrown in the inner try/catch block, you can modify your code as follows:

let retryCount = 0;

async function attemptToSendMessage() {
  while (retryCount &lt; 5) {
    try {
      await new Promise((resolve, reject) =&gt; {
        channel.assertQueue(
          name,
          { durable: true, arguments: { &quot;x-queue-type&quot;: &quot;quorum&quot; } },
          async (error, queue) =&gt; {
            if (error) {
              reject(error); // Reject the promise if an error occurs
              return;
            }

            if (queue) {
              try {
                channel.sendToQueue(name, Buffer.from(message));
                resolve(); // Resolve the promise if the message is sent successfully
              } catch (e) {
                reject(e); // Reject the promise if an error occurs while sending the message
              }
            }
          }
        );
      });
      break; // Exit the while loop if the message is sent successfully
    } catch (e) {
      console.log(e);
      retryCount++; // Increase the retry count
    }
  }

  if (retryCount === 5) {
    throw new Error(&quot;Failed to send message after 5 attempts.&quot;);
  }
}

// Usage
try {
  await attemptToSendMessage();
} catch (e) {
  // Handle the error here
  console.log(e.message);
}

答案2

得分: 1

以下是您要翻译的内容:

"你不应该将回调函数传递给 channel.assertQueue,尤其不是异步的回调函数,而是应该使用 promisify 它。通过 await,然后可以在外部的 try/catch 中捕获错误。

你可能正在寻找以下代码:

async function attemptToSendMessage() {
  for (let retryCount = 0; retryCount < 5; retryCount++) {
    try {
      const queue = await new Promise((resolve, reject) => {
        channel.assertQueue(
          name,
          { durable: true, arguments: { "x-queue-type": "quorum" } },
          (error, queue) => {
            if (error) reject(error);
            else resolve(queue);
          }
        );
      });
      if (queue) {
        await channel.sendToQueue(name, Buffer.from(message));
      }
      return; // 如果成功发送消息,则退出循环
    } catch (e) {
      console.error(e);
    }
  }
  throw new Error("在尝试了5次后仍然无法发送消息。");
}

但是,假设您正在使用 这个 API,您甚至不需要自己将 assertQueue 函数进行 promisify - 如果您不传递回调函数,它已经返回一个 promise。因此,可以进一步简化为:

async function attemptToSendMessage() {
  for (let retryCount = 0; retryCount < 5; retryCount++) {
    try {
      const queue = await channel.assertQueue(
        name,
        { durable: true, arguments: { "x-queue-type": "quorum" } }
      );
      if (queue) {
        await channel.sendToQueue(name, Buffer.from(message));
      }
      return; // 如果成功发送消息,则退出循环
    } catch (e) {
      console.error(e);
    }
  }
  throw new Error("在尝试了5次后仍然无法发送消息。");
}

希望这对您有所帮助。

英文:

You shouldn't pass a callback to channel.assertQueue, and not an async one for certain, instead you should promisify it. With await, you can then catch the errors in the outer try/catch.

You're probably looking for

async function attemptToSendMessage() {
  for (let retryCount = 0; retryCount &lt; 5; retryCount++) {
    try {
      const queue = await new Promise((resolve, reject) =&gt; {
        channel.assertQueue(
          name,
          { durable: true, arguments: { &quot;x-queue-type&quot;: &quot;quorum&quot; } },
          (error, queue) =&gt; {
            if (error) reject(error);
            else resolve(queue);
          }
        );
      });
      if (queue) {
        await channel.sendToQueue(name, Buffer.from(message));
      }
      return; // Exit the loop if the message is sent successfully
    } catch (e) {
      console.error(e);
    }
  }
  throw new Error(&quot;Failed to send message after 5 attempts.&quot;);
}

However, assuming you are using this API, you don't even need to promisify the assertQueue function yourself - it already returns a promise if you don't pass a callback. So simplify further to

async function attemptToSendMessage() {
  for (let retryCount = 0; retryCount &lt; 5; retryCount++) {
    try {
      const queue = await channel.assertQueue(
        name,
        { durable: true, arguments: { &quot;x-queue-type&quot;: &quot;quorum&quot; } },
      );
      if (queue) {
        await channel.sendToQueue(name, Buffer.from(message));
      }
      return; // Exit the loop if the message is sent successfully
    } catch (e) {
      console.error(e);
    }
  }
  throw new Error(&quot;Failed to send message after 5 attempts.&quot;);
}

huangapple
  • 本文由 发表于 2023年5月11日 18:23:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76226588.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定