您可以在另一个异步成员函数中等待一个异步成员函数吗?

时间:2020-04-22 00:32:46

标签: javascript async-await

我有一个类似以下内容的课程:

class Loader
{
    async load()
    {
        let pending = [...];
        return new Promise( (resolve, reject) => 
        {
            while(pending.length > 0)
            {
                await this._loadAsset(pending.pop());
            }
            resolve();
        });
    }

    async _loadAsset(asset)
    {
        return new Promise( (resolve, reject) =>
        {
            // Loading logic goes here, eventually calling...
            resolve();
        });
    }
}

({pending是一个对象数组,我懒得在这里列出。)

我遇到的问题是,当我尝试加载脚本时,Chrome给我一个Uncaught SyntaxError: await is only valid in async function错误。据我所知,Loader的load_loadAsset方法都已声明为异步。我想念什么? while循环会使事情复杂吗?

4 个答案:

答案 0 :(得分:2)

回调函数未声明为async,因此您可以尝试添加如下异步代码:

return new Promise( async (resolve, reject) => 
  {
    while(pending.length > 0) {
      await this._loadAsset(pending.pop());
  }
  resolve();
});

但是Promise.all() function

是解决许多未决承诺的更好选择

答案 1 :(得分:2)

您可以将load函数简化为:

async load()
{
    let pending = [...];
    while(pending.length > 0)
    {
        await this._loadAsset(pending.pop());
    }
}

不需要内部承诺构建。

您也可以这样做:

load()
{
    let pending = [...];
    return Promise.all(pending.map(i => this._loadAsset(i)));
}

答案 2 :(得分:0)

问题是您传递给Promise构造函数的匿名函数使用await,但未声明为async

return new Promise( (resolve, reject) =>  // this function uses await but is not async
    {
        while(pending.length > 0)
        {
            await this._loadAsset(pending.pop());
        }
        resolve();
    });

通常,如果您不包装需要回调的内容,则无需使用Promise构造函数。在这种情况下,您根本不需要它,只需将while循环作为load主体的一部分即可:

async load()
{
    let pending = [/*...*/];
    while(pending.length > 0)
    {
        await this._loadAsset(pending.pop());
    }
}

答案 3 :(得分:0)

您不应从async函数返回承诺。这是因为在幕后,从async函数返回的任何值都将包装在一个promise中:

// The following function
async function foo() {
    await someAsyncFunction();
    return "done";
}

// Is the same as
function bar() {
    return new Promise((resolve) => {
        someAsyncFunction().then(() => resolve("done"));
    });
}

因此,您的代码应重写为:

class Loader
{
    async load()
    {
        let pending = [...];

        while(pending.length > 0)
        {
            await this._loadAsset(pending.pop());
        }
    }

    async _loadAsset(asset)
    {
        // Loading logic happens here, but instead of calling resolve(), just return. Remember to add await to any async operation.
    }
}