异步函数重新进入而不被调用

async function re-entering without being called

这很可能是由于我对 JavaScript 的经验有限,但我一直无法弄清楚。这是一个Vue 2 + Typescript项目,但具体问题与Vue或Typescript无关

好的。所以我在我的一个组件中添加了以下功能。该组件的主要目的是获取 PDF 文件和 return 其第一页的光栅化版本 Blob。这是我的功能:

async importButtonHandler () {
  if (this.file) {
    const blob = await this.pdfToBlob(this.file)
    if (blob) {
      const file2 = new File([blob], 'raster_pdf', { type: 'image/png' })
      // Further processing
    }
  }
}

async pdfToBlob (pdfFile: File): Promise<Blob|null> {
  const canvas: HTMLCanvasElement = document.createElement('canvas')
  const buffer = await this.readFileAsync(pdfFile)
  const typedarray = new Uint8Array(buffer)

  // get handle of pdf document
  const doc = await pdfjsLib.getDocument(typedarray).promise

  // get handle of page
  const pdfpage = await doc.getPage(1)

  // get viewport to render the page at required scale
  const viewport = pdfpage.getViewport()

  // set canvas height same as viewport height
  canvas.height = viewport.height
  canvas.width = viewport.width

  const renderContext: RenderParameters = {
    canvasContext: canvas.getContext('2d') as CanvasRenderingContext2D,
    viewport: viewport
  }

  // render the page contents in the canvas
  await pdfpage.render(renderContext).promise

  return new Promise((resolve, reject) => {
    try {
      canvas.toBlob(resolve)
    } catch (error) {
      reject(error)
    }
  })
}

readFileAsync (file: File): Promise<ArrayBuffer> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()

    reader.onload = () => {
      resolve(reader.result as ArrayBuffer)
    }

    reader.onerror = reject

    reader.readAsArrayBuffer(file)
  })
}

它命中函数 pdfToBlob 并从中调用 readFileAsync,将文件正确读入 buffer,但紧接着(在 const typedarray = new Uint8Array(buffer) 上)而不是执行那一行,它再次点击 pdfToBlob 函数然后抛出一个异常说:

TypeError: Cannot read properties of undefined (reading 'getDocument')

我一直想不明白为什么它又进入了这个函数(没有其他地方调用这个函数)。

我的直觉是,我在函数中 return 是关于 Promise,但我的所有实验都没有给我任何线索。

谁能帮我弄清楚这里出了什么问题?

想通了(有点)。

首先,我的 pdfjsLib 需要在调用 getDocument 之前正确导入并提供 worker。这是我第二个问题的原因。下面是在 Vue 2/Typescript 项目中导入 lib 和 worker 的正确方法:

import * as pdfjsLib from 'pdfjs-dist'
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry'

然后向图书馆提供工作人员并调用getDocument:

pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker
const doc = await pdfjsLib.getDocument(YOUR_PDF_DATA).promise

我的 OP 中的其余代码工作正常。请注意,pdf.worker.entry 没有类型定义(或者至少我在任何地方都找不到它们),但它仍然有效。

第一个多次调用处理程序的问题似乎是 Vuetify 中的一个已知问题(或者行为,如果你愿意的话)。他们建议在定义 click 属性(如 @click.stop="importButtonHandler")时使用 nativepreventstop 来减轻这种行为。我试过没有成功。我的处理程序仍然被调用两次。在我的特定情况下,这不会造成任何功能性损害,所以我现在可以接受它,但我可以想到这种行为可能会造成灾难性后果的情况。

希望这对以后的人有所帮助。