There is an array which contains some image urls.
const imgs = [{
src:'./canvas-img1.jpg',
pos: 20
}, {
src: './canvas-img2.jpeg',
pos: 25
}]
I am trying to laod these images once in my application and then store them as cache for future use so that i don't have to load them again and again. I am using these images to draw them on canvas. I am doing the following steps.
Here is my code
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)
})
})
}
But when I console "can_imgs.length" in "then", it consoles zero. It should be array of length 2. What am I doing wrong?
Your then
is called before the images are actually loaded - so before img.onload
is triggered.
To solve your problem, wrap each individual image in a promise and await all of them before finally resolving the loadImage promise:
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)
})
})
})
}