-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Proposal: Provide an "Async Aware" operator: #25986
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
Comments
+1, this would be an awesome feature. |
It is unreadable, but it gets more readable if you introduce temporary variables:
Another option is to add a post-fix operator meaning the same thing as
Obviously not a good syntax, it's unreadable too :) |
I agree with @lrhn. It would be much better if you try to write the more readable (and clear) source code. P.S. |
Of course we can introduce local variables, and most of the time we do it. But it introduces lot of noise and completely unnecessary boilerplate, compare:
to a version that would have a variable in between of all - that is not used for anything other than visible text. I have never seen this chained awaits in production code, but it happens in most of the tests we have. There was a number of complaints we received when we moved to async pageloader, and they were:
into:
then this problem would go away. |
@rkj I do not think that the bunch of operations with the same operator can be replaced in a single operation (with a single operator which will be applied to each operand). We do not mean matrix operations, but talk about the operations of the random data (which may alternate with types). |
I disagree. Eg. // phase 0
// Enter f1()
await f1();
// Leave f1()
...
...
// phase 1
// Enter f2()
var x = await f2();
// Leave f2() This is the same as: f1();
yield return;
f2();
var x = yield return; When you try to |
@mezoni "awaits often need to be nested, leading to confusion about where to put awaits" was a feedback from many engineers at Google using the async https://github.com/google/pageloader tests. Most experienced developers are not confused by this at all, but new people certainly are. But I would leave that aside, new operator won't help with confusion much. The problem about nesting is real though. We have hundreds of occurrences, even though we actively discourage it in code reviews - to be replaced with vars, as you mentioned earlier. But this is really a lipstick on a pig, as when we used sync API before the code was much nicer and compact. As per unary operator, I am not a compiler person, but with my limited understanding of it, the proposal for '->' would mean to be a binary operator that could be implemented roughly as this pseudocode:
|
This is a very bad style of programming. expect( await( await (await childElement).description1)).innerText. "blah"); What do you think? Is this code good or bad (see below)? expect( func( func (func (childElement)).description1)).innerText. "blah"); What is your solution in such case (with many calls to
|
Let me start with func() - I have not seen something like that too often - (assuming you mean Going back to the original request, it is concerned with the form of As per the code example, as Ty mentioned it is unreadable, and bad, and what we currently do is we do split it in multiple lines, but this have negative overall effect of tests readability. If you look at my example from #25986 (comment) var billingInternal = await appBar.billingInternal;
var billingInternalVisibleText = await billingInternal.vsibileText;
expect(billingInternalVisibleText, 'Internal');
var lcsCustomer = await appBar.lcsCustomer;
var lcsCustomerVisibleText = await lcsCustomer.visibleText
expect(lcsCustomerVisibleText, 'LCS');
... ? It has 3x as many lines, actual expect is somewhat hidden, and there is lot of repeated strings. We mostly use page object to move this code to, so the tests stay clean so more realistically we would have: expect(await appBar.billingInternalVisibleText, 'Internal');
expect(await appBar.lcsCustomerVisibleText, 'LCS'); but this comes with the cost that now the appBar PO must have all the specific methods that are ever used in the test unwrapped inside, making them longer and less generic - all for our dislike to parenthesis/missing this feature. |
// 2 operations of member access // 2 operations of member access This is not the same statements. First statement produces 2 computations when second statement produces 4 computations. P.S. |
What about .await (used by rust)? expect(childElement.await.description1.await.innerText. "blah"); |
The It should be a non-breaking change because |
Any update on this? |
final store = Store()
..await init()
..await login(); It would be better to reopen #23000 |
Any updates? |
This comment was marked as off-topic.
This comment was marked as off-topic.
in a nutshell Would love some good meta-programming, although I dont even know how I'd do that in rust :D |
Definitely a language feature, so I'll defer to dart-lang/language/#25 and the issue here. |
While it is helpful to unravel futures using async/await, when the non-future item you need is several futures deep, the awaits quickly become hard to read. This comes up a lot in testing/pageloader objects
Example:
How about introducing an async operator to make this a little cleaner? Something like this:
The first await is for the Future returned by inner text. the "->" operator sees that the left side is a future, awaits it, then acts as the access operator. Doesn't have to be "->", but I like the parallel of de-futurizing to pointer dereferencing in c++.
The text was updated successfully, but these errors were encountered: