DalmarWolf
DalmarWolf

Reputation: 73

Trouble with async & await in Javascript

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:

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;
        }
    }
}

Upvotes: 4

Views: 100

Answers (1)

DalmarWolf
DalmarWolf

Reputation: 73

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.

Upvotes: 2

Related Questions