I've got a class that does something like the following:
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
is an array of objects that I'm too lazy to list out here.)
The problem I'm having is that Chrome is giving me an Uncaught SyntaxError: await is only valid in async function
error when I try to load my script. As far as I can tell, Loader's load
and _loadAsset
methods have both been declared async. What am I missing? Is the while loop complicating things?
The callback function is not declared async
, so you could try adding async like:
return new Promise( async (resolve, reject) =>
{
while(pending.length > 0) {
await this._loadAsset(pending.pop());
}
resolve();
});
But an even better option for resolving a lot of pending promised is the Promise.all() function
You can simplify your load
function to:
async load()
{
let pending = [...];
while(pending.length > 0)
{
await this._loadAsset(pending.pop());
}
}
Theres no need for the inner promise construction.
You could also do this:
load()
{
let pending = [...];
return Promise.all(pending.map(i => this._loadAsset(i)));
}
The problem is that the anonymous function you're passing to the Promise
constructor uses await
but is not declared async
:
return new Promise( (resolve, reject) => // this function uses await but is not async
{
while(pending.length > 0)
{
await this._loadAsset(pending.pop());
}
resolve();
});
Generally you won't need to use the Promise
constructor if you're not wrapping something that takes a callback. In this case, you don't need it at all, you can just have the while loop be part of load
's body:
async load()
{
let pending = [/*...*/];
while(pending.length > 0)
{
await this._loadAsset(pending.pop());
}
}
You should not return a promise from an async
function. That's because under the hood, any value returned from async
functions will be wrapped into a 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"));
});
}
So your code should be rewritten to:
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.
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.