0

In our app, we have problems with developers using async where it is not needed (the code is syncronous) and this is sometimes causing problems with code running in unexpected order or boolean statements returning true where they should not, because the caller might not use await e.g. on a simple getter function.

Example:

async function aFunctionThatIsJustSyncronous() {
    return false;
}

// would evaluate to true
if(aFunctionThatIsJustSyncronous()) {
}

I am searching for ways to detect this and remove superfluous async statements in the code. Are there any linters that can detect this, or do we just have to watch out? It has bitten us some times in the past...

Paul Weber
  • 6,518
  • 3
  • 43
  • 52
  • 1
    There are linter rules that warn you if you don't await an async function (or a function that returns a Promise), but I can't find any that can analyze all of your code to check if you don't need to have a function be async. I've never ran into this issue myself, this should be able to be caught in code reviews and tests. – Samathingamajig Feb 07 '23 at 06:39
  • 1
    "*Another example*" -> `// val would be still false here` no, It's most definitely going to be `true`. – VLAZ Feb 07 '23 at 06:41
  • 1
    In some cases, you may want to have an async call within an async function and don't wait for its completion. Nothing can detect if async is needed in such scenarios. I would recommend covering the code with unit tests and relying on them. Code ownership also helps to distribute and manage responsibility for technical debts. – RAllen Feb 07 '23 at 06:42
  • 2
    @RAllen "*Nothing can detect if async is needed in such scenarios.*" the heuristic is simple - is there `await` inside the async function? If yes, the function needs to be async. If no, then it doesn't need to be `async`. You can call async functions in non-async functions - there is no issue in that. You just cannot `await` them. So if you want a fire and forget (or you want to use the promise API to handle results) then you don't need the calling function to be async. – VLAZ Feb 07 '23 at 06:45
  • 1
    RE: the first example. TS already flags it as a potential problem: [Playground Link](https://www.typescriptlang.org/play?#code/IYZwngdgxgBAZgV2gFwJYHsI2AMSVNTAFQAthkBJEAKQRGQGVIoAnTdOgCgEoYBvAFAxhMFgFNkCFljjAANiDEBuAQF8BAgPSaYAdw5yAJjDEA3eQnJiYydDZYIxA1HE658hCKXJVa9JtBsEBwgPLyCqkA) That's without extra linters. – VLAZ Feb 07 '23 at 06:48

1 Answers1

0

After looking around i found some lints that might help us resolve this problem.

@typescript-eslint/no-misused-promises

https://typescript-eslint.io/rules/no-misused-promises/

This rule prevents you from forgetting to await an async function in a place where it would be easy to miss.

@typescript-eslint/no-floating-promises

https://typescript-eslint.io/rules/no-floating-promises

This rule prevents floating Promises in your codebase. A floating Promise is a Promise that doesn't have any code to handle potential errors.

Found this here: https://maximorlov.com/linting-rules-for-asynchronous-code-in-javascript

Paul Weber
  • 6,518
  • 3
  • 43
  • 52