await-thenable
Disallow awaiting a value that is not a Thenable.
Extending "plugin:@typescript-eslint/recommended-type-checked"
in an ESLint configuration enables this rule.
Some problems reported by this rule are manually fixable by editor suggestions.
This rule requires type information to run.
A "Thenable" value is an object which has a then
method, such as a Promise.
The await
keyword is generally used to retrieve the result of calling a Thenable's then
method.
If the await
keyword is used on a value that is not a Thenable, the value is directly resolved, but will still pause execution until the next microtask.
While doing so is valid JavaScript, it is often a programmer error, such as forgetting to add parenthesis to call a function that returns a Promise.
module.exports = {
"rules": {
"@typescript-eslint/await-thenable": "error"
}
};
Try this rule in the playground ↗
Examples
- ❌ Incorrect
- ✅ Correct
await 'value';
const createValue = () => 'value';
await createValue();
Open in Playgroundawait Promise.resolve('value');
const createValue = async () => 'value';
await createValue();
Open in PlaygroundAsync Iteration (for await...of
Loops)
This rule also inspects for await...of
statements, and reports if the value being iterated over is not async-iterable.
for await...of
loops used on an array of Promises?While for await...of
can be used with synchronous iterables, and it will await each promise produced by the iterable, it is inadvisable to do so.
There are some tiny nuances that you may want to consider.
The biggest difference between using for await...of
and using for...of
(plus awaiting each result yourself) is error handling.
When an error occurs within the loop body, for await...of
does not close the original sync iterable, while for...of
does.
For detailed examples of this, see the MDN documentation on using for await...of
with sync-iterables.
Also consider whether you need sequential awaiting at all. Using for await...of
may obscure potential opportunities for concurrent processing, such as those reported by no-await-in-loop
. Consider instead using one of the promise concurrency methods for better performance.
Examples
- ❌ Incorrect
- ✅ Correct
async function syncIterable() {
const arrayOfValues = [1, 2, 3];
for await (const value of arrayOfValues) {
console.log(value);
}
}
async function syncIterableOfPromises() {
const arrayOfPromises = [
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3),
];
for await (const promisedValue of arrayOfPromises) {
console.log(promisedValue);
}
}
Open in Playgroundasync function syncIterable() {
const arrayOfValues = [1, 2, 3];
for (const value of arrayOfValues) {
console.log(value);
}
}
async function syncIterableOfPromises() {
const arrayOfPromises = [
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3),
];
for (const promisedValue of await Promise.all(arrayOfPromises)) {
console.log(promisedValue);
}
}
async function validUseOfForAwaitOnAsyncIterable() {
async function* yieldThingsAsynchronously() {
yield 1;
await new Promise(resolve => setTimeout(resolve, 1000));
yield 2;
}
for await (const promisedValue of yieldThingsAsynchronously()) {
console.log(promisedValue);
}
}
Open in PlaygroundOptions
This rule is not configurable.
When Not To Use It
If you want to allow code to await
non-Promise values.
For example, if your framework is in transition from one style of asynchronous code to another, it may be useful to include await
s unnecessarily.
This is generally not preferred but can sometimes be useful for visual consistency.
You might consider using ESLint disable comments for those specific situations instead of completely disabling this rule.
Type checked lint rules are more powerful than traditional lint rules, but also require configuring type checked linting.
See Troubleshooting > Linting with Type Information > Performance if you experience performance degredations after enabling type checked rules.