代码之家  ›  专栏  ›  技术社区  ›  dotNET

异步函数在未被调用的情况下重新进入

  •  0
  • dotNET  · 技术社区  · 4 年前

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

    好的。所以我在我的一个组件中添加了以下函数。该组件的主要用途是获取PDF文件,并以 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 正确,但在那之后立即(on const typedarray = new Uint8Array(buffer) )它没有执行那一行,而是命中 pdfToBlob 函数,然后抛出一个异常:

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

    就我的一生而言,我不明白它为什么会再次进入函数(没有其他地方可以调用这个函数)。

    我的直觉是,这是关于我在功能中回归的承诺,但我所有的实验都没有让我找到任何线索。

    有人能帮我弄清楚这里出了什么问题吗?

    0 回复  |  直到 4 年前
        1
  •  1
  •   dotNET    4 年前

    想明白了(有点)。

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

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

    然后将worker提供给库并调用getDocument:

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

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

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

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

    推荐文章