es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

El error lanzado por un método de clase no es capturado por el manejador de solicitudes.

Creé una clase Transporter para enviar correos electrónicos:

export class MailTransporter {
  receiver: string;
  private transporter: Transporter;

  constructor(receiver: string) {
    this.receiver = receiver;
    this.transporter = this.getTransporter();
  }

  private getTransporter() {
    const { MAIL_USERNAME: user, MAIL_PASSWORD: pass, MAIL_HOST: host, MAIL_PORT: port } = process.env;

    if (!user || !pass || !host || port) {
      // LA SIGUIENTE LÍNEA ARROJA UN ERROR
      throw new Error('Especificar MAIL_USERNAME, MAIL_PASSWORD, MAIL_HOST y MAIL_PORT en el archivo .env');
    }

    const transporter = nodemailer.createTransport({
      host,
      port: Number(port),
      secure: true,
      auth: {
        user,
        pass,
      },
    });

    return transporter;
  }

  public async sendMail(formValues: string) {
    const values: FormValues = JSON.parse(formValues);
    const message: SendMailOptions = {...};

    await this.transporter.sendMail(message, (err, info) => {
      if (err) {
        throw err;
      }

      console.log('Correo electrónico enviado con éxito. Información:\n', info);
    });
  }
}

Y llamando a la función sendMail desde la función handler:

export default async function Handler(req: NextApiRequest, res: NextApiResponse) {
  const { body } = req;

  try {
    const response = await MessageTransporter.sendMail(body); // MessageTransporter es una instancia de MailTransporter

    res.status(200).json({ success: true, message: 'OK' });
  } catch (error) {
    res.json({ success: false, message: 'No se pudo enviar el mensaje' });
  }
}

Pero el error arrojado en MailTransporter no se está capturando en Handler, en su lugar, recibo el error en mi consola <img src="https://i.imgur.com/E5V310u.png" alt="image">. Además, en mi navegador recibo un error 500 en mi solicitud POST.

¿Podría explicar qué está sucediendo allí? ¿Por qué el error no se captura dentro del try catch de handler?

También, soy bastante nuevo en las clases de JavaScript, así que si tiene algo que decir sobre el diseño de la clase, por favor hágalo.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema aquí es que la función sendMail de la clase MailTransporter está lanzando un error pero no está devolviendo nada. La palabra clave await se utiliza al llamar a la función sendMail en Handler, lo que significa que espera que se devuelva una promesa. Dado que la función sendMail no devuelve nada, el bloque try-catch en Handler no puede capturar el error lanzado por la función sendMail.

    Para solucionar esto, puedes envolver el callback de la función sendMail en una Promesa de esta manera:

    public async sendMail(formValues: string) {
        return new Promise((resolve, reject) => {
            const values: FormValues = JSON.parse(formValues);
            const message: SendMailOptions = {...};
    
            this.transporter.sendMail(message, (err, info) => {
                if (err) {
                    reject(err);
                }
    
                console.log('Correo enviado correctamente. Información:\n', info);
                resolve(info);
            });
        });
    }
    

    Ahora, la función sendMail devolverá una Promesa y el try-catch en Handler debería capturar correctamente cualquier error lanzado por sendMail.

    En cuanto al diseño de la clase, no hay nada inherentemente incorrecto con la clase MailTransporter. Está manejando correctamente la lógica de transporte de correo electrónico y el manejo de errores. Sin embargo, siempre es bueno modularizar el código tanto como sea posible y separar las responsabilidades. Por ejemplo, podrías tener una clase separada para analizar los valores del formulario y construir el mensaje de correo electrónico. De esta manera, la clase MailTransporter no tendría que preocuparse por los valores del formulario y podría centrarse únicamente en el envío del correo electrónico.

Comments are closed.