承诺不在 thenable 中提供更新的数组
Promise not giving updated array in thenable
有一个包含一些图片网址的数组。
const imgs = [{
src:'./canvas-img1.jpg',
pos: 20
}, {
src: './canvas-img2.jpeg',
pos: 25
}]
我试图在我的应用程序中加载这些图像一次,然后将它们存储为缓存以备将来使用,这样我就不必一次又一次地加载它们。我正在使用这些图像在 canvas 上绘制它们。我正在执行以下步骤。
- 我发起了一个加载所有图片的承诺。 Promise 加载图像并将它们存储到数组中。
- 一旦承诺得到解决,我就会在 canvas
上绘制它们
这是我的代码
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 的数组。我做错了什么?
问题是您希望 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()
- 就像在您的原始代码中一样。
希望对您有所帮助!
您的 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)
})
})
})
}
有一个包含一些图片网址的数组。
const imgs = [{
src:'./canvas-img1.jpg',
pos: 20
}, {
src: './canvas-img2.jpeg',
pos: 25
}]
我试图在我的应用程序中加载这些图像一次,然后将它们存储为缓存以备将来使用,这样我就不必一次又一次地加载它们。我正在使用这些图像在 canvas 上绘制它们。我正在执行以下步骤。
- 我发起了一个加载所有图片的承诺。 Promise 加载图像并将它们存储到数组中。
- 一旦承诺得到解决,我就会在 canvas 上绘制它们
这是我的代码
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 的数组。我做错了什么?
问题是您希望 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()
- 就像在您的原始代码中一样。
希望对您有所帮助!
您的 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)
})
})
})
}