1

I have difficulties with iterating through array of objects which contains image. As my code below shows the array in console looks kind of empty but when I open it in console, I see all this objects also with iteration numbers. I can't google and get to the point how to transform it into proper working array to make for in loop and iterate through it in Vue.js. I attach you the code where comments says more than my description.

        const frameImage = [
        {
            url: 'http://www.realmadryt.pl/fotki/_up/newsy/lukamodric_165.png'
        },
        {
            url: 'http://www.realmadryt.pl/fotki/_up/newsy/florentinoperez_11.jpg'
        },
        {
            url: 'http://www.realmadryt.pl/fotki/_up/newsy/ramosbarkinsta1.jpg'
        },
        {
            url: 'http://www.realmadryt.pl/fotki/_up/newsy/lukamodric_165.png'
        },
        {
            url: 'http://www.realmadryt.pl/fotki/_up/newsy/florentinoperez_11.jpg'
        },
        {
            url: 'http://www.realmadryt.pl/fotki/_up/newsy/ramosbarkinsta1.jpg'
        },
    ];

    let createdImages = [];

    frameImage.forEach(item => {
        const image = new Image();
        image.src = item.url;
        image.onload = () => {
            // set image only when it is loaded
            createdImages.push({
                image,
                width: image.width,
                height: image.height,
                x: 0,
                y: 0,
                draggable: true
            });
        };
    });
    console.log(createdImages)


    // nothing happens
    createdImages.forEach(item => {
        console.log(item)
    });

    //also nothing happens
    for(img in createdImages) {
        console.log(img);
    }

    //length is actually 0?
    console.log(createdImages.length)

Also jsFiddle: LINK

2
  • 3
    Nothing is happening because you are looping over createdImages before the onload has fired and populated it. Commented Dec 4, 2018 at 23:33
  • 1
    Oh, I didn't think that it is async operation. Thanks! Commented Dec 4, 2018 at 23:35

1 Answer 1

1

I would map the array of URLs to an array of promises that resolve with your object when the image has loaded. Then use Promise.all to wait for them all to load (resolve). For example

Promise.all(frameImage.map(({ url }) => new Promise((resolve, reject) => {
  const image = new Image()
  image.onload = () => resolve({
    image,
    width: image.width,
    height: image.height,
    x: 0,
    y: 0,
    draggable: true
  })
  image.onerror = reject
  image.src = src
}))).then(createdImages => {
  // now you can iterate
}).catch(err => {
  console.error('Could not load all images', err)
})
Sign up to request clarification or add additional context in comments.

4 Comments

Unfortunately, I still have problem with returning these createdImages from my method. In a nuthsell createdImages should be returned from outer method which wraps this Promise, how can I achieve that? I know that I have to do it from .then() callback function but I have no idea how
Oh and I forgot to say that I am using Vue.js and this method is global in "eventBus" state and on my component I use computed property to render these images with v-for. Maybe you know better way to achieve that.
Yes, use Vuex. This sort of thing is perfect to put into an asynchronous action. See Returning Promises from Vuex actions
Thanks, but it is not that big project and now I achieve what i want by watching computed property which fires when the global images state change and then I push converted state into component own imageArr, is it bad?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.