typescript 在.svelte文件中工作的FileReader.Load代码在.ts文件中无法按预期工作

2skhul33  于 2023-04-07  发布在  TypeScript
关注(0)|答案(1)|浏览(130)

我很难理解为什么我的代码不工作,我需要一些帮助

onMount(async() => {

  // download the media file
    if (post.file_name) {
      await fetch(`/api/file?fileName=${post.file_name}`, {
        method: 'GET'
      })
      // convert the file into displayable image, video, or audio
      .then(async res => {
        const blob = await res.blob()
        if (blob.type.includes('image')) {
          mediaType = 'image'
          let reader = new FileReader()
          reader.readAsDataURL(blob);
          reader.onload = (event) => {
            media = event.target?.result
          }
        }
        else if (blob.type.includes('video')) {
          mediaType = 'video'
          media = URL.createObjectURL(blob)
        }
        else if (blob.type.includes('audio')) {
          mediaType = 'audio'
          // TODO implement this
        }
      })
      .catch(err => {
        console.error(err);
      })
    }

然后,我移动了该代码,并将日志记录添加到.ts文件中,并从同一个.svelte文件调用它
.ts文件

export function getFileRepresentation(fileName: string) {

    let file: FileRepresentation = {
        string: '',
        type: undefined
    }

    fetch(`/api/file?fileName=${fileName}`, {
        method: 'GET'
    })
    // convert the file into displayable image, video, or audio
    .then(async res => {
        const blob = await res.blob()
        if (blob.type.includes('image')) {
            file.type = 'image'
            let reader = new FileReader()
            reader.readAsDataURL(blob);
            reader.onload = (event) => {
                file.string = event.target?.result
                console.log('in promise');
                console.log(file.string); // DEBUGGING
            }
        }
        else if (blob.type.includes('video')) {
            file.type = 'video'
            file.string = URL.createObjectURL(blob)
        }
        else if (blob.type.includes('audio')) {
            file.type = 'audio'
            // TODO implement this
        }
    })
    .catch(err => {
        console.error(err);
    })
    
    console.log('on return');
    console.log(file.string); // DEBUGGING

    return file
}

.svelte文件

onMount(async() => {
   if (post.file_name) {
      const file = await getFileRepresentation(post.file_name)
      media = file.string
      mediaType = file.type
    }

.ts文件中的新代码不再起作用。console.logs显示首先调用的是'on return',file.string是空字符串,然后调用'in promise',其中字符串具有正确的值。为什么这段代码在这里的工作方式与.svelte文件中的不同?这都是客户端代码,所以我真的很困惑。
第53-59行的特定代码没有按预期工作,但我注意到第6-63行可以工作,因此我不太理解FileReader.load()的工作原理
编辑:用代码片段替换屏幕截图

mftmpeh8

mftmpeh81#

在Svelte文件中,您更新本地状态,执行顺序并不重要;在提取的代码中,您尝试返回一个对象,但情况并非如此。
顺序是错误的,您首先返回对象,然后在fetch完成时异步设置其内容。Svelte不会被通知这些更改,因为代码在组件外部。
如果你使用的是await,那么我建议你在读取的时候也使用它。为了等待文件读取器的结果,那部分可以是turned into a promise

try {
  const res = await fetch(...);
  const blob = await res.blob();
  // ...
  return file;
}
catch (error: any) {
  // what used to be in `.catch(...)`
}

如果你要保留Promise链,你必须返回一个Promise,也就是异步代码开始的地方,最后一个then应该返回最终的file对象。

return fetch(...)
  .then(res => {
    // ...
    return file;
  })

(You可能还想检查获取结果的响应代码,有一个实用程序属性ok,它检查它是否在200-299范围内。

相关问题