The waitFor function has been marked as "experimental" for two years now:
https://github.com/dart-lang/sdk/blob/ec8dcba611678ddff4bc11a7d521ad944323b444/sdk/lib/cli/wait_for.dart#L71
(see https://dart-review.googlesource.com/c/sdk/+/28920/ for its introduction)
Can we remove this line at this point? The experiment has clearly run its course. Either we need to remove this comment or we need to deprecate it (if we think it's a failed experiment for some reason).
There is value in something like this for CLI apps, of which there will be many more now that dart2native has landed, and I'd love us to provide reliable guidance. If there are better alternatives towaitFor, I'd love to know about them myself!
This function should be removed. It is fundamentally incompatible with Dart's event loop model.
OK. If that really is the case, then can we get it marked as @deprecated so we can start the countdown?
Leaving it around causes confusion, as evidenced by the fact that I just spent time introducing it into a CLI app I was writing. The code is cleaner than the highly-contagious async / await that I had before, but if it's not good code then I'd prefer to be forewarned...
If I recall correctly this was being used by @nex3 in SASS.
Yes, we rely heavily on waitFor()鈥攖here's no other way in Dart to call out to asynchronous APIs from otherwise-synchronous code. Please don't remove it.
Is the alternative to use then()?
@rmacnak-google, how do we resolve this?
Using then() is not an alternative. You want interface that looks synchronous but performs asynchronous actions inside. This is indeed in contradiction with Dart's event model as @rmacnak-google says and this function probably should not have been added in the first place.
Currently the library has been hidden from the public documentation by @mit-mit
I don't think we currently can resolve this further at the moment: in general a lot of engineers are in favour of removing it, but I don't think we can given that dart-sass depends on it.
@nex3 how does the code that depends on waitFor work on node? I recall that you could run dart-sass in two modes: native and translated to JS. Is this still the case?
Describing waitFor() as "in contradiction with Dart's event model" is too strong鈥攑lenty of languages support an event-loop based model while also being compatible with synchronous calls. This is the basis of the concept of fibers, for example, and very similar to how Go's goroutines work. waitFor() is just an implementation of the special case of that concept with a single stack shared between all events.
For what it's worth, I strongly believe full fiber support on the VM would be a substantial benefit to Dart.
@nex3 how does the code that depends on
waitForwork on node? I recall that you could rundart-sassin two modes: native and translated to JS. Is this still the case?
In JS mode, we currently use the fibers package. We're exploring the possibility of switching to worker threads along with the Atomics.wait() function, although whether we do so in practice depends on how high the overhead of spawning a thread turns out to be.
I would like to add my voice to keeping waitFor and removing the experimental tag.
I've just implemented a package call dshell which provides tooling and a library for building cli applications.
https://pub.dev/packages/dshell
dshell makes heavy use of waitFor (as in virtually every exposed function uses it).
The use of waitFor greatly simplifies the dshell users experience and actually makes the library safer to use.
During our early experiementation for dshell we played with an async version of the library.
We found it was very easy to miss a single 'await' and the whole script would start mis-behaving in unexpected and hard to debug ways.
As an example you might have started an async write to a file, forget to await the write and so end up trying to move a the file before the write completes.
We were spending time scanning through our code to ensure that every method up the stack was properly awaited.
There is also little gain in providing an async experience when writing cli scripts as there is no user expectation that the UI should be responsive when long running tasks are running.
Removing waitFor would be determintal for writers of cli applications and would completely kill dshell.
So I would much rather it waitFor remains :)
Most run loops I've used can be run recursively, in order to handle situations like this. libuv is the only one I can think of that can't. CFRunLoop, Qt event loop and GMainLoop all are reentrant in order to allow synchronous callbacks. Since in dart we have no control over the loop itself, waitFor is as good as it gets for an escape hatch.
Most helpful comment
I would like to add my voice to keeping waitFor and removing the experimental tag.
I've just implemented a package call dshell which provides tooling and a library for building cli applications.
https://pub.dev/packages/dshell
dshell makes heavy use of waitFor (as in virtually every exposed function uses it).
The use of waitFor greatly simplifies the dshell users experience and actually makes the library safer to use.
During our early experiementation for dshell we played with an async version of the library.
We found it was very easy to miss a single 'await' and the whole script would start mis-behaving in unexpected and hard to debug ways.
As an example you might have started an async write to a file, forget to await the write and so end up trying to move a the file before the write completes.
We were spending time scanning through our code to ensure that every method up the stack was properly awaited.
There is also little gain in providing an async experience when writing cli scripts as there is no user expectation that the UI should be responsive when long running tasks are running.
Removing waitFor would be determintal for writers of cli applications and would completely kill dshell.
So I would much rather it waitFor remains :)