In Polymer there is a this.job() function that handles the delayed processing of events. How do you access this functionality from polymer.dart?
#override
void attached() {
super.attached();
dom.window.onMouseMove.listen(mouseMoveHandler);
}
PolymerJob mouseMoveJob;
void mouseMoveHandler(dom.MouseEvent e) {
print('mousemove');
mouseMoveJob = scheduleJob(mouseMoveJob, onDone, new Duration(milliseconds: 500));
}
void onDone() {
print('done');
}
If the job isn't rescheduled for 500ms it is executed.
In polymer this is often used during initialization when
xxxChanged(old);
is called several times succinctly because xxx is updated on changes from several other states which are initialized one after the other but it is enough when xxxChanged is executed for the last update (a much shorter timeout should be used then like 0-20 ms depending whether xxxChanged is only called from sync or also from async code.
Another situation where I used this pattern (but not using PolymerJob) is where an #observable field is bound to a slider <input type="range" value='{{slider}}'>.
This invokes sliderChanged(oldVal, newVal) very often in a short interval when you move the knob. The execution of the update is expensive and can't be finished between two such calls see http://bwu-dart.github.io/bwu_datagrid/example/e04_model.html for an example.
Without some delayed execution this would be very cumbersome to use.
Try using Future:
doJob() => print('hi');
new Future(doJob).then((_) => print('job is done'));
Here are the docs for the Future class.
Related
Dart offers a FutureOr class, that allows writing:
FutureOr<int> future;
future = 42; // valid
future = Future.value(42); // also valid
I would assume that FutureOr would be useful to remove the unnecessary delay caused by the event loop if the value can be read synchronously.
But that doesn't seem to be the case, as showcased by:
import 'dart:async';
void main() async {
print('START');
futureOrExample();
print('END');
}
void futureOrExample() async {
FutureOr<int> futureOr = 42;
print('before await');
await futureOr;
print('end await');
}
which prints:
START
before await
END
end await
when I would expect:
START
before await
end await
END
In that case, why does FutureOr (or more generally await 42) work this way?
Similarly, what's the purpose of FutureOr in that situation since it produces the same result as Future?
I know that I could use SynchronousFuture to achieve the desired result, but I'm just trying to understand what's the use of FutureOr.
The use of FutureOr, as introduced with Dart 2, is to allow you to provide either a value or a future at a point where the existing Dart 1 API allowed the same thing for convenience, only in a way that can be statically typed.
The canonical example is Future.then. The signature on Future<T> is Future<R> then<R>(FutureOr<R> action(T value), {Function onError}).
The idea is that you can have an action on the future's value which is either synchronous or asynchronous. Originally there was a then function which took a synchronous callback and a chain function which took an asynchronous callback, but that was highly annoying to work with, and in good Dart 1 style, the API was reduced to one then method which took a function returning dynamic, and then it checked whether it was a future or not.
In Dart 1 it was easy to allow you to return either a value or a future. Dart 2 was not as lenient, so the FutureOr type was introduced to allow the existing API to keep working. If we had written the API from scratch, we'd probably have done something else, but migrating the existing asynchronous code base to something completely different was not an option, so the FutureOr type was introduced as a type-level hack.
The await operation was also originally defined to work on any object, long before FutureOr existed. For consistency and smaller code, an await e where e evaluated to a non-future would wrap that value in a future and await that. It means that there is only one quick and reusable check on a value (is it a future, if not wrap it), and then the remaining code is the same. There is only one code-path.
If the await worked synchronously on non-Future values, there would have to be a synchronous code path running through the await, as well as an asynchronous path waiting for a future. That would potentially double the code size, for example when compiling to JavaScript (or worse, if there were more awaits in the same control flow, you could get exponential blow-up for a naive implementation). Even if you avoided that by just calling the continuation function synchronously, it would likely be confusing to some readers that an await would not introduce an asynchronous gap. A mistake around that can cause race conditions or things happening in the wrong order.
So, the original design, predating FutureOr, was to make all await operations actually wait.
The introduction of FutureOr did not change this reasoning, and even if it did, it would now be a breaking change to not wait in places where people expect their code to actually give time for other microtasks to run.
The await keyword always lock the function execution.
Writing:
await 42
Is equivalent to:
await Future.value(42)
The reason being:
This is how await works in Javascript
it makes the behavior of await consistent.
Now, what's the purpose of FutureOr then?
FutureOr was never intended as a way to potentially make await synchronous.
Instead, it is an implementation detail of Future.
Without FutureOr, writing the following would not compile:
Future(() {
return 42; // compile error, not a Future
});
Future<int> future;
future.then((value) {
return value * 2; // compile error, not a Future
});
Instead, we would have to wrap all values in a Future.value like so:
Future<int> future;
future.then((value) {
return Future.value(value * 2);
});
for those who are still confused
I found good explanation https://itnext.io/what-is-futureor-in-dart-flutter-681091162c57 without diving into details
This piece of code could explain the target and real use cases of FutureOr
abstract class IDBService {
FutureOr<String> fetch();
}
class FirebaseRemoteService extends IDBService {
#override
Future<String> fetch() async => await 'data';
}
class LocalHiveDbService extends IDBService {
#override
String fetch() => 'data';
}
so in implementations of IDBService
the return type can be Future or String at the same time now!
Coming late to the discussion.
Updating my Dart comprehension - pardon my C++/JS -ish approach.
Seems like this would be useful for singleton initiation. Consider following:
import 'dart:async';
class AClass {
static String _info = '';
static FutureOr<String> get info async {
if (_info.isEmpty) {
print('--> is empty...');
_info = await Future.delayed(Duration(seconds:2),
() => "I'm alive!!");
}
else {
print('--> not empty');
}
return _info;
}
}
Future<void> main() async {
String info = await AClass.info;
print('Fist call: ' + info);
info = await AClass.info;
print('Second call: ' + info);
}
It works as expected - in either case, whether the _info member has been instantiated or not, the getter returns a valid string.
It works fine if I just use a Future<String> specifier in the getter, too. The current implementation makes FutureOr seem mostly like a self-documentation exercise (can return a Future<String> or a String...)
But, even if await currently always locks the execution, a future update may allow it to work as expected, in which case using the FutureOr construct would anticipate updates.
(Aside: I imagine this example could be condensed using an Optional wrapping the _info member, but that's a different exercise...)
I needed to use FutureOr today. I wanted to call a function that might be asynchronously (not always).
String callbackOne() => "hello";
Future<String> callbackTwo() async => (await Future.delayed(Duration(seconds: 1),() => "This is a sentence"));
Problem
I can do getLengthOfResult(callbackOne), but not getLengthOfResult(callbackTwo). Conversely, if accept an async callback, I can't use the sync callback.
DartPad
Future<int> getLengthOfResult(String Function() callback) async {
return callback().length;
}
Solution
DartPad
Future<int> getLengthOfResult(FutureOr<String> Function() callback) async {
// I can await on callbackOne, even though it returns a String.
final result = await callback();
return result.length;
}
main() {
getLengthOfResult(callbackOne);
getLengthOfResult(callbackTwo);
}
Taking this example from the doc:
Stream<List<Hero>> heroes;
// ยทยทยท
void ngOnInit() async {
heroes = _searchTerms.stream
.transform(debounce(Duration(milliseconds: 300)))
.distinct()
.transform(switchMap((term) => term.isEmpty
? Stream<List<Hero>>.fromIterable([<Hero>[]])
: _heroSearchService.search(term).asStream()))
.handleError((e) {
print(e); // for demo purposes only
});
}
Say I want to "trigger" the stream at ngOnInit().
After some tests, I find this can be done by calling void search(String term) => _searchTerms.add(term); just after this:
await Future.delayed(Duration(milliseconds: 1));
Seems that the _searchTerms call inside ngOnInit() is not await.
Could anyone explain why this works that way, or what I am doing wrong?
It isn't exactly clear what you are trying to do here, but some background that might help.
Angular lifecycle methods can't be interrupted. They also will not wait for async actions. They are simply callbacks that will be called at the point of the angular lifecycle. Asking angular to wait for you to do work at some unknown point to it is not possible. What if the action never completed? What happens to the rest of the subtree? You would be in some weird state that would invalidate much of the logic and the app.
Instead we use change detection/variables to change the state of the component to handle these async actions. So you could show a progress indicator using a boolean variable until the rpc comes back and then show the results by flipping the variable.
My question stems from an issue almost identical to the one here (which did not end up getting a satisfactory answer):
https://vaadin.com/forum/thread/13932610
Like this person, I expected that upon closing the browser that my app was open in, a detach event would proc; however, this did not happen. I've tried adding a detach listener, overriding the detach method, and doing both at the same time, but none of them were successful. As for how I know the detach event was not called, my detach event is a simple print statement - that does not show up in the output.
Note that like in the aforementioned thread, I've already set the heartbeat interval (2 seconds in my case) and set closeIdelSessions to be true. So, I thought I would just have to wait six seconds, but that's certainly not been the case.
When I try this (find the essential parts of the code below), the detach() is eventually being called. I run this with Jetty, and I did not touch its default. It tooks some ~45 minutes after closing the Browser, when I saw "Detach called" logged on console. So yes, the time is lengthy. The reason is that the last UI is cleaned up only after HttpSession is expired (which depends on application container etc. settings). If you want to do forced clean up quicker, you need to use https://vaadin.com/directory/component/cleanupservlet-add-on
#Push
#SuppressWarnings("serial")
public class DemoUI extends UI {
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = DemoUI.class, heartbeatInterval=5, closeIdleSessions=true)
public static class Servlet extends VaadinServlet {
}
#Override
public void detach() {
System.out.println("Detach called");
}
#Override
protected void init(VaadinRequest vaadinRequest) {
...
}
I want to execute same future function with different values. The order is not important. But I want to execute some functions after the above future function. My idea is
addrMapList.forEach((addrMap){ //length is 3
exeQuery(sql).then((result){
print(result);
});
});
print('All finished');
// other actions
Future exeQuery(String sql){
var c=new Completer();
Random rnd=new Random();
c.complete(rnd.nextInt(100));
return c.future;
}
But the result is
All finished
72
90
74
But I need a result like
72
90
74
All finished
How can this implement in dart.. Please help.
Here is modified version of your sample to work as you expected it to.
First of all, you should understand how asynchronous code works, and why it was not in your case:
When you write constructions like <some future>.then( (){...} ); you are not immediately running code defined inside .then( ). You just defining a callback, to be called later. So, in your code, you're defined 3 callbacks, and then, immediately, printed "All finished", at the time when no of your futures even started to work. At this moment they are just sitting in dart's event loop and waiting for a chance to be executed. And they will get that chance only when you finish execution of current code, and not a moment earlier, because Isolate is run as a single thread.
I used Future.wait() to wait for multiple futures because you said order is not important. This is more efficient then waiting Futures one by one. But if order is important, you have to use Future.forEach(), it will not start execution of second Future until first one is completed.
One more thing in your code is that your function returning a Future is actually synchronous, because it always returns already completed Future. This is also changed in dartpad sample above to better visualize how asynchronous code works.
forEach can't be used this way. Use await for instead (the enclosing function needs to be async)
Future someFunc() async {
await for (var addrMap in addrMapList) {
var result = await exeQuery(sql);
print(result);
}
// other action
}
I'm writing a C++/CX component to be consumed by Window's store Apps. I'm looking for a way to accomplish what Task.Delay(1000) does in C#.
Old Question, but still unanswered.
You can use
#include <chrono>
#include <thread>
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
This will need C++11, which shouldn't be a problem when using C++/CX.
After one year of using C++/CX, I have a general and reasonably correct answer to this question.
This link (from the Visual C++ Parallel Patterns Library documentation) includes a snippet for a function called complete_after(). That function creates a task that will complete after the specified number of milliseconds. You can then define a continuation task that will execute afterwards:
void MyFunction()
{
// ... Do a first thing ...
concurrency::create_task(complete_after(1000), concurrency::task_continuation_context::use_current)
.then([]() {
// Do the next thing, on the same thread.
});
}
Or better yet, if you use Visual C++'s coroutines capabilities simply type:
concurrency::task<void> MyFunctionAsync()
{
// ... Do a first thing ...
co_await complete_after(1000);
// Do the next thing.
// Warning: if not on the UI thread (e.g., on a threadpool thread), this may resume on a different thread.
}
You could create a concurrency::task, wait for 1000 time units and then call the ".then" method for the task. This will ensure that there is at least a wait of 1000 time units between the time you created the task and between the time it gets executed.
I'm not going to claim to be a wizard - I'm still fairly new to UWP and C++/CX., but what I'm using is the following:
public ref class MyClass sealed {
public:
MyClass()
{
m_timer = ref new Windows::UI::Xaml::DispatcherTimer;
m_timer->Tick += ref new Windows::Foundation::EventHandler<Platform::Object^>(this, &MyClass::PostDelay);
}
void StartDelay()
{
m_timer->Interval.Duration = 200 * 10000;// 200ms expressed in 100s of nanoseconds
m_timer->Start();
}
void PostDelay(Platform::Object^ sender, Platform::Object ^args)
{
m_timer->Stop();
// Do some stuff after the delay
}
private:
Windows::UI::Xaml::DispatcherTimer ^m_timer;
}
The main advantage over other approaches is that:
it's non-blocking
You're guaranteed to be called back on the XAML UI thread