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.

Escribir en una plantilla XLSX y luego enviarla como respuesta en una función diferente, siempre devuelve indefinido.

Lo que intento hacer:

Las solicitudes llegan a mi servidor para descargar un archivo que contiene datos. La parte de descarga está en el front-end y funciona. Recojo los datos en el backend y luego quiero escribirlos en una plantilla existente y devolver los datos.

Este es el controlador para la solicitud:

async handle(request: Request, response: Response) {

try {

  const fileName = 'test.xlsx'
  const binary = objectsToTemplateWorkBook()

  response.setHeader(
    'Content-Disposition',
    'attachment; filename=' + fileName
  )

  response.setHeader('Content-Type', 'application/vnd.openxmlformats')
  response.end(binary, 'binary')
} catch (error) {
  console.log(error)
  response.send(error)
}


}

Esta es la función que se supone que debe escribir los datos en la plantilla.
js
export const objectsToTemplateWorkBook = (): 
Promise<any> => {
  var XlsxTemplate = require('xlsx-template')
  var dataBlob
  // Load an XLSX file into memory
  const blob = fs.readFile(
    path.join(dirname, 'test_template.xlsx'),
    function (err, data) {
      console.log(dirname)
      // Create a template
      var template = new XlsxTemplate(data)

  // Replacements take place on first sheet
  var sheetNumber = 1

  // Set up some placeholder values matching the placeholders in the template
  var values = {
    people: [
      { name: 'John Smith', age: 20 },
      { name: 'Bob Johnson', age: 22 },
    ],
  }

  // Perform substitution
  template.substitute(sheetNumber, values)

  // Get binary data
  dataBlob = template.generate()
  // ...
}


)
  return dataBlob
}

La función parece escribir los datos en la plantilla porque si registro el dataBlob dentro del método fs.readFile, me muestra el archivo. Sin embargo, el return dataBlob siempre devuelve indefinido. Sé que esto se debe a la naturaleza asíncrona, pero sinceramente no tengo idea de cómo arreglarlo. Entonces, mi pregunta para ti es: ¿cómo puedo llevar el dataBlob a mi controlador para enviarlo como respuesta?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Puedes usar la API de Promise para asegurarte de que la función objectsToTemplateWorkBook devuelva el dataBlob antes de que la función handle envíe la respuesta.

    Primero, necesitas asegurarte de que la función fs.readFile devuelva una Promise en lugar de usar un callback. Puedes hacer esto utilizando el método util.promisify.

    js
    const util = require('util');
    const fs = require('fs');
    const readFile = util.promisify(fs.readFile);

    Luego, puedes usar la palabra clave await para esperar a que se resuelva la promesa de readFile antes de continuar con el resto de la función objectsToTemplateWorkBook.

    export const objectsToTemplateWorkBook = async (): 
    Promise<any> => {
      var XlsxTemplate = require('xlsx-template')
      var dataBlob
      // Carga un archivo XLSX en memoria
      const data = await readFile(
        path.join(__dirname, 'test', 'template.xlsx')
      )
      // Crea una plantilla
      var template = new XlsxTemplate(data)
    
      // Se realizan las sustituciones en la primera hoja
      var sheetNumber = 1
    
      // Se establecen algunos valores de marcador de posición que coinciden con los marcadores de posición en la plantilla
      var values = {
        people: [
          { name: 'John Smith', age: 20 },
          { name: 'Bob Johnson', age: 22 },
        ],
      }
    
      // Se realiza la sustitución
      template.substitute(sheetNumber, values)
    
      // Obtiene los datos binarios
      dataBlob = template.generate()
      // ...
      return dataBlob
    }
    

    Por último, puedes utilizar la palabra clave await en la función handle para esperar a que se resuelva la promesa de objectsToTemplateWorkBook antes de enviar la respuesta.

    “`js
    async handle(request: Request, response: Response) {

    try {

    const fileName = 'test.xlsx'
    const binary = await objectsToTemplateWorkBook()
    
    response.setHeader(
      'Content-Disposition',
      'attachment; filename=' + fileName
    )
    
    response.setHeader('Content-Type', 'application/vnd.openxmlformats')
    response.end(binary, 'binary')
    

    } catch (error) {
    console.log(error)
    response.send(error)
    }
    }
    “`

Comments are closed.