Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

res.send is not waiting for my async function to finish before sending the response to the front end on my Express server app

I am trying to create full stack app that lets the user input the URL and captures the screenshot using Puppeteer. On my backend express server I am using app.post to send the response to the front end which creates the image for download.

Here's my backend:

app.post('/api/screenshot', (req, res) => {
  const { url } = req.body

  let screenshot = takeScreenshot(url)
  res.send({ result: screenshot })
  // next()
})

async function takeScreenshot(url) {
  const browser = await puppeteer.launch({
    headless: true,
    args: ['--no-sandbox']
  });
  const page = await browser.newPage();
  await page.goto(url, { waitUntil: 'networkidle0' });
  const screenshot = await page.screenshot()

  await browser.close();
  return screenshot;
}

My front end JS has an event listener for the ss-btn. When it is clicked, it triggers the post request to the backend which runs the takeScreenshot function. Then it generates the link for the download

$("#ss-btn").on("click", function (event) {
  event.preventDefault();
  var url = $("#url").val().trim();

  $.post("/api/screenshot", { url: url })
    .then(res => {
      const { result } = res
      const blob = new Blob([result], { type: 'image/png' })
      const link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = `your-file-name.png`
      link.click()
    })
});

Right now, when I click the ss-btn, I get the popup right away asking where I want to save the image. But it doesn't look like the screenshot is being sent back to the front end. The png file is corrupted and I cannot open it.

TIA

like image 697
Kevin Avatar asked Oct 28 '25 01:10

Kevin


1 Answers

You have to await the result of takeScreenShot(). It is an async function so it returns a promise that eventually resolves to your screenshot so to wait for it to complete and to get its value, you have to use either await or .then() on the promise it returns:

app.post('/api/screenshot', async (req, res) => {
  const { url } = req.body

  try {    
      let screenshot = await takeScreenshot(url)
      res.send({ result: screenshot })
  } catch(e) {
      // catch errors and send error status
      console.log(e);
      res.sendStatus(500);
  }
});

Changes:

  1. Make request handler async so you can use await.
  2. Use await to wait for the screenshot result.
  3. Add try/catch to catch a rejection from the await.
  4. Send error status if there's an error.
like image 93
jfriend00 Avatar answered Oct 30 '25 15:10

jfriend00



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!