【问题标题】:Trouble with async & await in JavascriptJavascript中的异步和等待问题
【发布时间】:2021-11-01 14:14:11
【问题描述】:

这是我在这里的第一个问题,我一直试图环顾四周,看看是否找到了有意义的东西,但到目前为止,我还无法真正思考如何做到这一点。

好的,所以我的问题是这样的,我目前正在制作一个脚本,该脚本将从 API 中获取(卡片的)图片并将它们显示在 Canvas 上,到目前为止这一切都很好。

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

我遇到的问题是我允许用户单击图像以将其更改为不同的版本,当他们单击图像时,我通过 API 发送查询来列出其他类似图像.这有时需要一点时间,因此会给我一个 GET net::ERR_FILE_NOT_FOUND 错误,但如果再次单击它确实有效。所以我想在尝试更改图片之前等待代码完成制作数组。

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

我尝试了几种方法:

  • 我已尝试将grabPics 设为异步函数并使用grabPics().then(...其他所有...) 的东西。
  • 我尝试将 nextPic 设为异步函数并使用 await grabPics();以几种不同的方式,使用 Promise 等,甚至声明自定义 Promise。

我遇到的问题是,当我做这些事情时,我避免了使用原样生成代码时收到的错误消息,但它永远不会改变图片,而且它似乎永远不会执行 nextPic 函数即使再次点击……我错过了什么?

我似乎无法真正思考在哪里放置 async、await 或 then() 的东西。

编辑: 我的尝试:

尝试 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;
            }
        });
    }
}

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

【问题讨论】:

  • 如果您发布您的尝试,我们可能会指出问题所在。把所有东西都放在async 听起来是正确的方向。
  • 您是否尝试过将grabPics 函数设为异步/等待函数?这样做,请确保您在 postData 函数之前放置了 await。然后再次确保您的 nextPic 函数是 async/await,例如 this.nextPic = async function() 另外,在 this.grapPics 函数之前添加 await
  • 无需包装自定义 Promise。只需在postData 调用之前添加return

标签: javascript async-await


【解决方案1】:

好的,我想我找到并解决了我的问题。

正如 Aleksey 指出的那样,在 postData 之前添加 return 似乎有效。

但是,为什么它不起作用是因为返回包裹在 if(pics.length == 0) 支票中。所以我添加了一个 else 并返回它自己的,这似乎允许 nextPic 在重复点击时继续。

【讨论】:

    猜你喜欢
    • 2021-10-07
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 2021-10-11
    • 1970-01-01
    • 2018-12-09
    • 2017-04-01
    • 2020-04-20
    相关资源
    最近更新 更多