GithubHelp home page GithubHelp logo

Comments (6)

bradzacher avatar bradzacher commented on June 1, 2024 1

When I talked to Josh about this previously it seemed like this was a legacy option so I wasn't planning to use it.

It's not! Many codebases use it because it provides that nice, self-documenting, no-disable-comment way to mark a promise as intentionally floating.

Josh calls it legacy because he doesn't like it and it originally became a part of the rule by accident. Way way back in the day someone did it by accident and asked for an option to catch it. And when it was added people learned it and liked it and so it became a common style.

At Canva we use it and people like it because it means no disable comments and no empty catches.


I think you're ultimately thinking about this too defensively.

A developer unfamiliar with the rule will not know what void is doing and not think twice about copy-pasting it.

You could replace void with literally any concept and have the same outcome! Disable comments, consuming functions, empty catches, no-call catches, etc. Even applies to any rule really as all rules enforce specific styles that people may copy and paste and misuse.

People will need to learn your codebase style and convention - there's likely many patterns within your codebases that are considered idiomatic style internally, but that are not used externally. It's a very common phenomenon in codebases as they evolve naturally!

Put it this way:
If someone blindly copy+pastes a voided promise to an async function and doesn't switch it to an await - they 100% would also copy paste an empty catch promise without awaiting or any other form really.

From my experience working within large react codebases (fb and canva) - you're more likely to have people forget to make a function async than you are to have people misuse the "anti-floating" tool. And both result in the same problem - that there is a floating promise - but the former is harder to track down because you need to find an unannotsted, floating promise. Whereas the void approach is very clear - just look for the void!


All that being said - I think ultimately what you want is #8404. You want to mark a promise as infallible and that is what that issue will allow you to do.

Ignoring promises in sync contexts is just a workaround for the issue of the rule reporting on infallible promises.

from typescript-eslint.

bradzacher avatar bradzacher commented on June 1, 2024

Because no-floating-promises has no good way to check if errors are caught in a function (ie using try-catch)

I'm not quite sure I understand what you mean by this. Could you give an example?


Have you considered the ignoreVoid option?
https://typescript-eslint.io/rules/no-floating-promises/#ignorevoid

It adds a declarative way for a developer to declare "I am intentionally not awaiting this promise" and it works in both sync and async contexts.

A lot of people like it because it is "symmetrical" with the await.


Personally I don't think this is a good option because often times you can create a promise and forget to await it, even in a sync context. If you ignore all promises in sync contexts then it's very easy to create floating promises accidentally - as in - you meant for it to be an async function but you forgot to do. So.

That is a massive bug vector in code!
OTOH if you leverage void or disable comments or some bespoke internal thing - you can enforce the floating promise is explicitly handled as opposed to implicitly handled or forgotten.

from typescript-eslint.

NotWoods avatar NotWoods commented on June 1, 2024

Unfortunately we have some developers that will see any tool we give as a hammer so I don't want to introduce void 😅 Already I've seen one promise-inside-promise nested code with 5 nested .catch(() => {}) instead of just using a flat promise chain. That's our current massive bug vector and I've talked with Josh a couple times and haven't found a good strict way to avoid this. We're currently choosing to turn off the rule because we'd prefer seeing bugs show up as unhandled promises rather than swallowing with catch.

(I guarantee if we turn on a no-empty-catch rule people will start just copy-pasting comments. I previously opened an issue because some devs write promise.catch; as a workaround).

Could you give an example?

async function foo() {
  try {
    await somePromise;
  } catch (error) {
    logger.log(error);
  }
}

// needs .catch or void to satisfy linter even though this code should be safe
foo();

from typescript-eslint.

bradzacher avatar bradzacher commented on June 1, 2024
async function foo() {
  try {
    await somePromise;
  } catch (error) {
    logger.log(error);
  }
}

// needs .catch or void to satisfy linter even though this code should be safe
foo();

What happens when logger.log throws an unhandled exception 😬

Jokes aside - #8404 is an enhancement that would allow you to build tooling for "guaranteed infallible promises" and have the rule understand that.


previously opened an issue because some devs write promise.catch; as a workaround

no-unused-expressions is your friend for preventing that!


Unfortunately we have some developers that will see any tool we give as a hammer so I don't want to introduce void 😅

I'm not sure I understand - how would "allow floating promises in sync contexts" be any better than "use void to mark floating promises in sync contexts"? It seems like it's worse?


At meta the pattern we used was a function like so:

function promiseDone(p: Promise<any>): void {
  p.catch(someGlobalPromiseErrorLogger);
}

useEffect(() => {
  promiseDone(Promise.resolve());
});

So like void it was clear and explicit that the intent was to not await the promise, and it also had the added benefit of ensuring the promise had error handling attached.

from typescript-eslint.

NotWoods avatar NotWoods commented on June 1, 2024

Thanks for showing the pattern from meta, that's good to know and something to investigate for us.

no-unused-expressions is your friend for preventing that!

We've turned this on since :) It solved that workaround but now unfortunately developers just use empty catch.

I'm not sure I understand - how would "allow floating promises in sync contexts" be any better than "use void to mark floating promises in sync contexts"? It seems like it's worse?

I don't want to allow using void in a context where await would work, such as an async function or promise chain. A developer unfamiliar with the rule will not know what void is doing and not think twice about copy-pasting it. That might be an improvement over no flag at all so it's something we can experiment with. When I talked to Josh about this previously it seemed like this was a legacy option so I wasn't planning to use it.

from typescript-eslint.

NotWoods avatar NotWoods commented on June 1, 2024

Sounds good, I'll explore using void in our codebase instead. I think it would be useful to have a rule/option to prevent it from being used in async functions but that's a different issue to this, so I'll close it :)

from typescript-eslint.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.