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.

Validador de Expresiones: Validación personalizada con funciones asíncronas.

Actualmente estoy tratando de validar algunas entradas en Express utilizando express-validator. Sé que lo típico es pasar esto como middleware separado en la ruta, pero necesitaba acceso al objeto res, así que lo escribí de la forma que se ve a continuación.

La parte con la que estoy luchando es el validador custom. Me gustaría que llamara a una función asíncrona store.todoListTitleExists(title) que consulta una base de datos y verifica si un título ya existe. Si el título no existe, mi intención es guardar un mensaje de error que pueda mostrar más tarde como un mensaje flash.

Actualmente, este código no funciona. He revisado la documentación pero no puedo entender cómo hacer que este validador personalizado y el mensaje de error funcionen adecuadamente ya que llama a una función asíncrona. Cualquier ayuda sería apreciada.

¡Gracias!

app.post("/lists/:todoListId/edit", 
    (req, res) => {
    let store = res.locals.store;
    let todoListId = req.params.todoListId;
    let title = req.body.todoListTitle;

await body('todoListTitle')
      .trim()
      .isLength({ min: 1 })
      .withMessage("Se requiere el título de la lista.")
      .isLength({ max: 100 })
      .withMessage("El título de la lista no puede tener más de 100 caracteres.")
      .custom(store.todoListTitleExists(title).then(titleExists => {
        if(titleExists) return Promise.reject('El título ya existe.');
      }))
Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para habilitar la validación asíncrona en express-validator, puede utilizar la palabra clave async delante del validador custom. También necesitas devolver una Promesa que resuelva a true o a un rechazo con un mensaje de error si la validación falla.

    En su código, está llamando directamente a store.todoListTitleExists(title) dentro del validador custom, lo cual no retornaría una Promesa, sino el resultado real de la llamada a la función. Para solucionar esto, puedes envolver la llamada a la función dentro de una Promesa y devolver eso en su lugar. Aquí está una versión actualizada de su código que debería funcionar:

    app.post("/lists/:todoListId/edit", async (req, res) => {
      let store = res.locals.store;
      let todoListId = req.params.todoListId;
      let title = req.body.todoListTitle;
    
      await body('todoListTitle')
        .trim()
        .isLength({ min: 1 })
        .withMessage("El título de la lista es requerido.")
        .isLength({ max: 100 })
        .withMessage("El título de la lista no puede contener más de 100 caracteres")
        .custom(async (title) => {
          const titleExists = await store.todoListTitleExists(title);
          if (titleExists) {
            throw new Error('El título ya existe');
          }
        })
    });
    

    En esta versión actualizada, estamos envolviendo la llamada a store.todoListTitleExists(title) dentro de una función async que devuelve una Promesa. Dentro de esa función, estamos esperando el resultado de la llamada a la función y luego comprobando si el título existe. Si existe, estamos lanzando un error con el mensaje de error correspondiente.

Comments are closed.