【问题标题】:Promise not giving updated array in thenable [duplicate]承诺不在thenable中提供更新的数组[重复]
【发布时间】:2020-07-04 17:06:18
【问题描述】:

有一个包含一些图片网址的数组。

const imgs = [{
    src:'./canvas-img1.jpg',
    pos: 20
}, {
    src: './canvas-img2.jpeg',
    pos: 25
}]

我试图在我的应用程序中加载这些图像一次,然后将它们存储为缓存以供将来使用,这样我就不必一次又一次地加载它们。我正在使用这些图像在画布上绘制它们。我正在执行以下步骤。

  1. 我发起了一个 Promise 来加载所有图像。 Promise 加载图像并将它们存储到数组中。
  2. 承诺解决后,我将它们绘制在画布上

这是我的代码

drawCanvas(){
    let canvas = document.getElementById("timeline-canvas")
    let canvas_container = document.getElementById("canvas-container")
    let ctx = canvas.getContext("2d")


    this.loadImage().then((can_imgs)=>{
        console.log(can_imgs.length) // this is coming as array of length 0
        this.state.can_imgs.map((item, i)=>{
            let x = (item.pos * window.innerWidth)/100
            ctx.drawImage(item.img, x,0, 100, 100);
        })
    })
    ctx.save()
}

//load images only once and cache them
loadImage = () => {
    return new Promise(resolve => {
        imgs.map((item, i)=>{
            let img1 = new Image()
            img1.src = item.src
            let x = (item.pos * window.innerWidth)/100
            img1.onload = function (e)
            {
                can_imgs.push({img: img1, pos: item.pos})
            }
        })
        this.setState({can_imgs: can_imgs}, ()=>{
             resolve(can_imgs)
        })

    })

}

但是当我在“then”中控制台“can_imgs.length”时,控制台为零。它应该是长度为 2 的数组。我做错了什么?

【问题讨论】:

    标签: javascript promise es6-promise


    【解决方案1】:

    问题是您希望 onload 同步调用,但它是异步发生的。因此can_imgs.push() 很可能发生在您将can_imgs 传递给resolve() 之后。

    我会尝试以下方法:

    let started = 0;
    let loaded = 0;
    
    imgs.map((item, i)=>{
       let img1 = new Image()
       img1.src = item.src
       let x = (item.pos * window.innerWidth) / 100
    
       started++
    
       img1.onload = (e) => {
          can_imgs.push({img: img1, pos: item.pos})
    
          loaded++
    
          if (started === loaded) {
             this.setState({can_imgs: can_imgs}, () => {
                resolve(can_imgs)
             })
          }
       }
    })
    

    使用started === loaded,您正在检查是否所有图像都已加载,因此可以调用resolve() - 就像在您的原始代码中一样。

    我希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      在实际加载图像之前调用您的 then - 所以在触发 img.onload 之前。

      要解决您的问题,请将每个单独的图像包装在一个承诺中,并在最终解决 loadImage 承诺之前等待所有图像:

      
      loadImage = () => {
          return new Promise(resolve => {
      
              let images = imgs.map((item, i)=> new Promise((resolve) => {
                  let img1 = new Image()
                  img1.src = item.src
                  let x = (item.pos * window.innerWidth)/100
                  img1.onload = function (e)
                  {
                      can_imgs.push({img: img1, pos: item.pos})
                      resolve()
                  }
              }))
      
              // wait for all images to resolve
              Promise.all(images).then(() => {
                  this.setState({can_imgs: can_imgs}, ()=>{
                      resolve(can_imgs)
                  })
              })
      
      
      
          })
      
      }
      

      【讨论】:

        猜你喜欢
        • 2020-10-30
        • 2018-03-19
        • 2020-05-17
        • 2018-07-21
        • 1970-01-01
        • 2014-03-20
        • 2019-11-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多