英文:
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 < 5) {
    try {
      await new Promise((resolve, reject) => {
        channel.assertQueue(
          name,
          { durable: true, arguments: { "x-queue-type": "quorum" } },
          async (error, queue) => {
            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("Failed to send message after 5 attempts.");
  }
}
// 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 < 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; // Exit the loop if the message is sent successfully
    } catch (e) {
      console.error(e);
    }
  }
  throw new Error("Failed to send message after 5 attempts.");
}
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 < 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; // Exit the loop if the message is sent successfully
    } catch (e) {
      console.error(e);
    }
  }
  throw new Error("Failed to send message after 5 attempts.");
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论