使用ES2017的async/await重构Promise和Promise.all

4

我有一个可用的照片上传处理程序,但我想看看如何使用async await工作。在此之前,以下是我使用promise的可用代码。

onChangePhotos = (e) => {
    e.preventDefault()

    let files = e.target.files

    if(files.length === 0) { return }

    const allow_photos_length = this.state.selectedAlbum.photos.length + files.length
    if(allow_photos_length > this.state.maxPhoto) {
      alert(`Maximum only ${maxPhoto} photos per album!`)
      return
    }

    this.setState({
      uploading_photo: true
    })

    let promises = []
    for(const file of files){
      promises.push(UploadApi.uploadPhoto('company', file))
    }

    Promise.all(promises)
    .then(responses => {

      let next_photos = []
      for(const [index, response] of responses.entries()) {
        const { upload_id, url } = response

        next_photos.push({photo_id: upload_id, url})

        if(responses.length === index + 1){
          this.setState({
            uploading_photo: false
          })
        }
      }

      this.setState({
        selectedAlbum: {
          ...this.state.selectedAlbum,
          photos: [
            ...this.state.selectedAlbum.photos,
            ...next_photos
          ]
        }
      })

    })
    .catch(err =>{
      this.setState({ uploading_photo: false })
      alert('failed to upload! Error: ' + err)
    })
  }

我将它转换为async await,webpack没有显示任何错误,但是当我尝试在我的Web应用程序上测试时,发现当我执行console.log(this)时,this未定义。

下面是我的async await尝试:

onChangePhotos = async (e) => {
    e.preventDefault()

    let files = e.target.files

    if(files.length === 0) { return }

    this.setState({
      uploading: true
    })

    let promises = []
    for(const file of files){
      const uploadPhotoPromise = await UploadApi.singlePhoto(file)
      promises.push(uploadPhotoPromise)
    }

    try {

      const responses = await Promise.all(promises)

      let next_photos = []
      for(const [index, response] of responses.entries()) {
        const { upload_id, url } = response

        next_photos.push({photo_id: upload_id, url})

        if(responses.length === index + 1){
          this.setState({
            uploading: false
          })
        }
      }

      this.setState({
        selectedAlbum: {
          ...this.state.selectedAlbum,
          photos: [
            ...this.state.selectedAlbum.photos,
            ...next_photos
          ]
        }
      })

    } catch(err) {
      this.setState({ uploading: false })
      alert('failed to upload! Error: ' + err)
    }
  }

什么问题?

“我收到了一个错误,看起来像是未定义‘this3’。” - 什么?你的代码中根本没有‘this3’。 - Bergi
@Bergi 我不知道这是我得到的,除了这个错误我没有看到其他错误。 - Sharon Chai
你在使用转译器吗?你在哪一行遇到了错误? - Bergi
@Bergi 我找到问题了。当我执行console.log(this)时,this未定义。我在我的.babelrc文件中有这个:["transform-runtime", { "polyfill": false, "regenerator": true }] - Sharon Chai
1个回答

2

由于缺乏信息,我不确定这个错误的意思是什么,但是您的承诺数组没有承诺,因为您已经使用了 await:

我建议将此更改为:

let promises = []
for(const file of files){
  const uploadPhotoPromise = await UploadApi.singlePhoto(file)
  promises.push(uploadPhotoPromise)
}

to:

const promises = [];

for(const file of files){
  promises.push(UploadApi.singlePhoto(file))
}

这不是同一件事吗?uploadPhotoPromise是一个promise,它被推入了promises数组中,不是吗? - Sharon Chai
1
你正在UploadApi.singlePhoto前面使用await。这意味着返回值不是一个Promise,而是Promise的解析值。 - Poul Kruijt
files.map 不是一个函数。 - Sharon Chai
Ah,files是一个FileList。没看到,我会更新我的答案。 - Poul Kruijt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接