4

This is my first question here, and I have been trying to look around to see if I find something that makes sense, but so far I'm been unable to really wrap my head around how to do this.

Okay, so my problem is this, I'm currently making a script that will grab pictures (of cards) from an API and display them on a Canvas, this all works great so far.

this.drawCard = function() 
{
    img.src = this.card_pic;
    img.onload = () => {
        c.drawImage(img, x, y, crdwid, crdhei); // Draws the card.
    }
}

Problem I'm running into is I'm allowing the user to click on an image to change it to a different version, when they click the image, I make a list of other similar images by sending a query through the API. This sometimes takes a moment, and so gives me an GET net::ERR_FILE_NOT_FOUND error, though it does work if you click again. So I'd like to wait for the code to finish making the array before trying to change picture.

this.grabPics = function()
{
    if(pics.length == 0)
    {
        console.log('Making Array of pics.');
        postData(this.prints).then((data) => { 
            // This .then works fine, and does the job correctly. 
            // It calls a function based on the cache fetched from this tutorial. https://www.sitepoint.com/cache-fetched-ajax-requests/
            for(var i = 0; i < data.total_cards; i++)
            {
                pics.push(data.data[i].image_uris.large);
            }
        });
    }
}

this.nextPic = function()
{
    if (this.reprint)
    {
        this.grabPics(); // I believe I need a await, or .then here.
        this.card_pic = pics[picNum]; // Because this uses the array from grabPics.
        this.drawCard(); // And this draws the next picture.
        picNum++; // Should probably do this earlier.
        if (picNum >= pics.length)
        {
        picNum = 0;
        }
    }
}

I have tried several methods:

  • I have tried to make grabPics an async function and using a grabPics().then( … everything else … ) thing.
  • I have tried to make nextPic an async function and using await grabPics(); in several different ways, using promises and such, even declaring custom promises.

The problem I run into is that when I do these things, I avoid the error message I get with having the code as is produces, but it never changes the picture, and it doesn't seem to ever execute the nextPic function again even when clicking again… what is it that I am missing?

I just seem to be unable to really wrap my head around where to put the async, await, or then() stuff.

EDIT: My attempts:

Attempt 1:

this.grabPics = async function()
{
    return new Promise(resolve => {
        if(pics.length == 0)
        {
            console.log('Making Array of pics.');
            postData(this.prints).then((data) => {
                for(var i = 0; i < data.total_cards; i++)
                {
                    pics.push(data.data[i].image_uris.large);
                }
                console.log(pics);
                resolve('true');
            });
        }
    });
}

this.nextPic = function() 
{
    if (this.reprint)
    {
        this.grabPics().then(resolve => {
            this.card_pic = pics[picNum];
            this.drawCard();
            picNum++;
            if (picNum >= pics.length)
            {
                picNum = 0;
            }
        });
    }
}

Attempt 2:

this.grabPics = function()
{
    return new Promise(resolve => {
        if(pics.length == 0)
        {
            console.log('Making Array of pics.');
            postData(this.prints).then((data) => {
                for(var i = 0; i < data.total_cards; i++)
                {
                    pics.push(data.data[i].image_uris.large);
                }
                resolve('go');
            });
        }
    }); 
}
    
this.nextPic = async function() 
{
    if (this.reprint)
    {
        const result = await this.grabPics();
        this.card_pic = pics[picNum];
        this.drawCard();
        picNum++;
        if (picNum >= pics.length)
        {
            picNum = 0;
        }
    }
}
3
  • If you post your attempts we can probably point out the problem. Making everything here async sounds like the right direction. Commented Apr 26, 2020 at 14:57
  • Have you tried to make grabPics function an async/await function? Doing that, make sure you have put await before postData function. Then again make sure your nextPic function is an async/await, like, this.nextPic = async function() Also, add await before this.grapPics function. Commented Apr 26, 2020 at 15:00
  • There is no need to wrap in custom Promise. just add return before postData call. Commented Apr 26, 2020 at 15:12

1 Answer 1

2

Okay, I think I found and solved my problem.

Adding return before postData as Aleksey pointed out seemed to work.

However, why it didn't work was because the return was wrapped in the if(pics.length == 0) check. So I added an else with a return of it's own, that seemed to allow nextPic to continue on repeated clicks.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.