-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Future.wait should support Flutter's SynchronousFuture #50204
Comments
Probably unsurprising, but I'm strongly opposed to supporting Both because it's unnecessarily complicating code that shouldn't need that complication, and because it's a game of infinite whack-a-mole to find all the places where code breaks when presented with a misbehaving future. There might be good use-cases for synchronously receiving a result, but then the code should not be using the I recommend introducing a different class, which is not a abstract class AsyncResult<T> {
Future<T> asFuture();
bool get isComplete;
T get value;
} and pass that around instead of Or adding methods to abstract class SynchronousFuture<T> ... {
bool get isComplete;
T get value; // Throws if completed with error, throws if not complete.
} and use those methods when you need the result immediately, but have the If you are willing to use The problem with all of these suggestions is that |
Thanks for the quick reply! In my opinion, neither of your proposal solve the problem at hand Both proposals significantly complexify interacting with the Future. They are hardly any different than
That's not true. The core of the issue is that the SynchronousFuture is abstracted (so received as The Not using This is a pretty bad trade-off IMO. |
In the end, I would describe the current situation as a lose-lose situation. As a package author, my package has abstracted the problem of a function that sometimes execute synchronously and sometimes asynchronously. But the language doesn't allow me to offer a simple way of interacting with the result.
So although the problem is conceptually solved by my package, the language/SDK prevents me from solving it for my users. |
OK, counterpoint to my previous post, because why have only one opinion? Most users don't write code that calls That means that as long as The big question is then what the list of essential functions is, how easy it is to fix them, and what the runtime cost/overhead will be? I'd assume everything in It does suggest that we are accepting the behavior of (I can see that To get back on my original high horse: What if |
We'd definitely still be here today 😄 Over the past years, I've raised various issues related to this problem For example, I've asked for making FutureOr<T> futureOr;
T value = @wait(futureOf); The problem is not specific to There are multiple workarounds to the issue. Although all the available existing solutions have a major flaw at the moment. For instance, even if this issue wasn't a problem, SynchronousFuture would still not be quite ideal We're currently stuck in a trinity of problem: Either the workaround is too complex, or it's silently failing, or it has very poor readability/writabily. For example one solution could be to tell users of my packages to stop using Then I could ask my users to write code such as: CustomFuture<int> add(int increment) {
return CustomFuture(() {
CustomFuture<int> a = getFuture();
return a.then((value) => value + increment);
});
} That would fix the flicker issue. But that's going back many years in the past just for one problem. So the issue isn't SynchronousFuture here. The issue is that we don't have an official solution to the problem at hand and can only try to hack one with what we can. |
While I fear the API risks, I think using I don't want everybody to return It's just a little breaking to make (So, make it type based so that
That way, you only get synchronous behavior if the static type is |
Ah, well, that for sure would be great! About the "FutureOr for speed!", I think this could be attenuated with lint rules. If there's a "await Future" or another future invocation that's always async, a lint could say "Don't use FutureOr as return value". The same thing could be applied to "await null" probably. |
If we do allow The problem with |
I don't mind an |
If I understand it correctly, this issue as well as dart-lang/language#2033 and usage of That is a use case specific to Flutter and is currently not possible because the UI build and layout phases (which can interleave) are synchronous and single pass. Instead of changing or extending Dart's async language features, the Flutter framework could be changed to support multiple build phases, where microtasks are executed in between build phases until no new microtasks are scheduled. For reference, browsers drain the microtask queue after dispatching an event before painting. I've filed a proposal (flutter/flutter#113763) for this in the Flutter framework repo. |
Any update on this ? |
Still no plan to change the implementation to support futures that do not follow the Consider every operation that actually works with a If you don't use The discussion here has mainly been about providing possible alternatives to |
Related thread: flutter/flutter#71554
It appears that
Future.wait
doesn't handleSynchronousFuture
gracefully, causing the following code to crash:I am aware that @lrhn mentioned how "SynchronousFuture is inherently incompatible with the specified Future semantics", accompanied by "Don't use
SynchronousFuture"
.But I don't think this is a reasonable recommendation.
SynchronousFuture
, although a bit unique, is an important use case.When caching asynchronous code, this can be the difference between a flicker or not in the UI. As replacing a
SynchronousFuture
with a normalFuture
would delay the resolution of theFuture
by one frame. This would in turn delay the UI rendering by one frame too.This matters because, besides
SynchronousFuture
, there is no other reasonable workaround.FuturOr
doesn't work for example, asawait futureOr
does not complete synchronously. At the same time, it is unreasonable to expect users to do:Writing such a code is not intuitive and cannot be refactored. Awaiting two
FutureOr
would involve writing this exact sequence of code twice. As such, this isn't a pattern that can be reasonably used at scale.So currently the only real solution is to use
SynchronousFuture
, as this is a reusable solution.With that consideration, I believe it would be reasonable to update
Future.wait
to supportSynchronousFuture
.The text was updated successfully, but these errors were encountered: