Henok Tesfaye
Henok Tesfaye

Reputation: 9570

How to use async/await inside promise executor to read pdf content?

import axios from 'axios'

export const findNumberOfPages = async pdfUrl => {
  return new Promise(async (resolve, reject) => {
    try {
      const response = await axios.get(pdfUrl, {
        headers: { 'Content-Type': 'application/pdf' }
      })

      const reader = new FileReader()
      reader.readAsBinaryString(new Blob([response.data]))
      reader.onloadend = () => {
        const pages = reader.result.match(/\/Type[\s]*\/Page[^s]/g)
        const count = pages?.length

        resolve(count)
      }
    } catch (error) {
      reject(new Error(`Error when fetching pdf: ${error.message}`))
    }
  })
}

I'm adding a utility to get number of pages in a pdf(https url) using File Reader API.

But eslint shows an error, Promise executor functions should not be async. (no-async-promise-executor)standard(no-async-promise-executor), and I want to await the axios request to get the pdf response. How can i await the axios request and resolve the number of pages on onloadend of FileReader?

enter image description here

Upvotes: 0

Views: 471

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074949

You don't need the promise constructor here. You would (although not quite in that way) if you had to use FileReader, but you don't, Blob has a text method that reads the blob as text:

import axios from 'axios';

export const findNumberOfPages = async pdfUrl => {
    try {
        const response = await axios.get(pdfUrl, {
            headers: { 'Content-Type': 'application/pdf' }
        });
        const result = await new Blob([response.data]).text();
        const pages = result.match(/\/Type[\s]*\/Page[^s]/g);
        const count = pages?.length;
        return count;
    } catch (error) {
        throw new Error(`Error when fetching pdf: ${error.message}`);
    }
};

I don't use axios, but I suspect that axios.get call is a bit off. You've specified a Content-Type, but you're not sending data (the Content-Type request header specifies the type of data you're sending, not receiving). Also, I suspect you don't need the Blob part of this at all.

Using the built-in fetch instead, I'd expect you could do it like this:

import axios from 'axios';

export const findNumberOfPages = async pdfUrl => {
    try {
        const response = await fetch(pdfUrl);
        if (!response.ok) {
            throw new Error(`HTTP error ${response.status}`);
        }
        const result = await response.text();
        const pages = result.match(/\/Type[\s]*\/Page[^s]/g);
        const count = pages?.length;
        return count;
    } catch (error) {
        throw new Error(`Error when fetching pdf: ${error.message}`);
    }
};

Upvotes: 4

Related Questions