Можете ли вы дождаться asyn c функции-члена в другой asyn c функции-члене? - PullRequest
0 голосов
/ 22 апреля 2020

У меня есть класс, который делает что-то вроде следующего:

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 были объявлены как asyn c. Что мне не хватает? В то время как l oop усложняет вещи?

Ответы [ 4 ]

2 голосов
/ 22 апреля 2020

Вы можете упростить вашу функцию 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 голосов
/ 22 апреля 2020

Функция обратного вызова не объявлена ​​async, поэтому вы можете попробовать добавить asyn c, например:

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

Но еще лучшим вариантом для разрешения большого количества ожидаемых обещаний является Функция Promise.all ()

0 голосов
/ 22 апреля 2020

Вы не должны возвращать обещание от функции async. Это потому, что под капотом любое значение, возвращаемое функциями async, будет заключено в обещание:

// 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.
    }
}
0 голосов
/ 22 апреля 2020

Проблема в том, что анонимная функция, которую вы передаете конструктору 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 конструктор, если вы не оборачиваете что-то, что требует обратного вызова. В этом случае вам это вообще не нужно, вы можете просто иметь время, пока l oop будет частью тела load:

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