Why is my synchronous code executing asynchronously? - reactjs

I'm trying to run some synchronous function which should wait for a certain time and then return control. But for some reason, it keeps executing asynchronously, or at least that's how it looks.
This is the code:
function pause(ms) {
var dt = new Date();
while (new Date() - dt <= ms) {
/* Do nothing */
}
}
console.log("start calculation..");
pause(3000);
console.log("calculation finished!");
this immediately shows the following in the console:
start calculation..
calculation finished!
There is no delay at all, as if the pause function is executed asynchronously.
I've tried 3 different versions of the pause function, it doesn't make any difference.
You can see this in the sandbox I put the code in.
(you must go to preferences - sandbox.config.json and turn of "Infinite loop protection" for it to work)
Why isn't the code running synchronously, first showing the "start calculation..." message, and then the second message after a 3 second delay?
Is there a better way to simulate running a time-expensive synchronous function?

Since my question has only been partially answered, I will provide the solution myself, in case other people have similar issues:
First of all, this code now works as intended in the console of Chrome, Chromium and Firefox. It didn't before, so perhaps there's been an upgrade to the javascript engine in this regard.
When running the code in the provided CodeSandbox though, it still logs the two lines simultaneously, after a 3 seconds delay.
As people have pointed out, 2 things could possibly be the cause of this:
the compiler removing empty loops
the console messages not refreshing as long as the loop is running
This code will fix both issues:
function pause(ms, start=new Date()) {
while (new Date() - start <= ms) {
setTimeout(()=>pause(ms,start))
}
}
console.log("start calculation..");
pause(3000);
console.log("calculation finished!");
Calling a SetTimeout (even with a 0 ms delay) will cause the rest of the code execution (a recursive function call) to be thrown back on the event loop for later processing, after allowing for the execution of event callbacks first. This ensures other events - such as logging of the console - will not be blocked.
It also puts some actual code inside the loop, so that the loop will not be removed by any compiler code optimisation.

Related

What is the purpose of next('r') in the context of an RxJS Subject

I'm still fairly new to the RxJS world (please pardon my semantics), but I've seen a few examples of code that creates a Subject to do some work, and then calls next(0), or next('r') on the subscription. It appears to re-run the stream, or rather fetch the next value from the stream.
However, when I tried using this to call an API for some data, it completely skips over the work it's supposed to do as defined in the stream (assuming it would "run" the stream again and get new data from the server), and instead my subscriber gets the 'r' or zero value back when I try to call next like that.
I get that making the subscription "starts execution of the stream", so to speak, but if I want to "re-run" it, I have to unsubscribe, and resubscribe each time.
Is it a convention of some kind to call next with a seemingly redundant value? Am I just using it in the wrong way, or is there a good use-case for calling next like that? I'm sure there's something fundamental that I'm missing, or my understanding of how this works is very wrong.
It's a good question, I definitely recommend you to read about hot and cold Observables.
cold Observables execute each time someone subscribes to it.
const a$ = of(5).pipe(tap(console.log))
a$.subscribe(); // the 'tap' will be executed here
a$.subscribe(); // and here, again.
hot Observables do not care about subscriptions in terms of execution:
const a$ = of(5).pipe(
tap(console.log),
shareReplay(1)
);
a$.subscribe(); // the 'tap' will be executed here
a$.subscribe(); // but not here! console.logs only once
In your example you are using Subject that represents cold Observable.
You can try to use BehaviorSubject or ReplaySubject - both of them are hot but be aware that they behave differently.
IN you example you can modify your Subject like the following:
const mySubject = new Subject();
const myStream$ = mySubject.pipe(
shareReplay(1)
);
myStream$.subscribe(x => console.log(x))
mySubject.next(1);
mySubject.next(2);
mySubject.next(3);

How to wait until an element is not changing in Selenium Webdriver?

I have begun to use explicit wait more and more to deal with asynchronous event on the page. For example i will wait for an element to be clickable before clicking it.
However many time i also face the situation when i need to wait an element to become stable, i.e. stop changing, before i will act on it. For example, i may do a query on a page, and wait for the search result (either shown in a list or a table) to stop changing, and then retrieve the results.
Off course, there will be a timeout period for this wait. So in a nutshell, i want to wait for a list or table while its values are not changed, say for 5 sec.
How to implement this kind of wait? Could anyone give a simple example in code, if possible?
Thanks,
Using FluentWait will do the job. Its advantage to implicitWait and explicitWait is that it uses polling and timeout frequency. For example, we have a timeout value of 5 seconds and 1 second for polling frequency. The element will be checked for every 1 second until it reaches the timeout value (5 sec). An exception is thrown if the timeout value is exceeded without having any result.
FluentWait is helpful in AJAX applications as well as in scenarios when element load time fluctuates often because it ignores specific types of exceptions like NoSuchElementExceptions while waiting for an element.
You can check the sample code for FluentWait here
I would do something like this. Basically you want to count what is changing, e.g. table rows, list elements, etc., wait X seconds, count again. If the count didn't change, you are done. If it did change, wait again.
int count = 0;
int newCount = 0;
boolean done = false;
while (!done)
{
newCount = driver.findElements(...).size();
if (newCount > count)
{
count = newCount;
}
else
{
// no new results, stop waiting
done = true;
}
Thread.sleep(2000);
}
Depending on your scenario, you might want to add an overall timeout so that you never exceed X minutes or whatever. Just add that to the while condition.

Having to use DelayedTask otherwise LoadMask doesn't show

I am doing a few processes that take time so I want to be able to show a mask, I use LoadMask. Problem is that the code that I want to run seems to run too quick and I presume is blocking the UI to show the mask. The process takes around 4 seconds so I know the mask isn't being enabled and disabled at the same time.
The way I got around this was to use a delayed task, but it kind of feels like a code smell.
Can I do this a different way?
Here is what I have
var myMask = new Ext.LoadMask(win, {});
myMask.show();
var task = new Ext.util.DelayedTask(function () {
....... // DO MY stuff and eventually do a myMask.hide()
task.delay(400);
It works great but I was wondering if this is the right way to go ?
If I remove the delayedtaks then the mask never seems to display, but the process does work.
Assuming your "process" is some kind of local sequential procedure, what you said above is pretty much correct. If your code is running a busy loop it won't relinquish control to the UI "thread" for the browser to redraw.
So you won't see the mask here;
mask();
busyLoop();
unmask();
But if you do:
mask();
setTimeout(function() {
busyLoop();
unmask();
}, 1);
It gives the browser time to draw before you get into your stuff.

AngularJS - ng-grid sliding window - table not updating from array change

I'm trying to use ng-grid with a sliding window of 100 records. The data is coming in realtime via signalR and every message trigger the following method:
onNewTrades(records) {
console.log("onNewRecord", records);
if (connectionStopped) return;
for (var i = 0; i < records.length; i++) {
if ($scope.recordsData.length > maxRecordsInTable)
$scope.recordsData.pop();
$scope.recordsData.unshift({
t: new Date(records[i][0]),
p: records[i][1],
a: records[i][2]
});
}
}
I have a threshold of 100 maxRecordsInTable before I start popping items off the end (before adding the new message to the front)
However, when it reaches my threshold the table simple stops updating. Strangely though, if I set a breakpoint on unshift(), the table does update with every "continue".
I suspect it's some kind of angular timing issue? I tried using $timeout()
Or may when I pop() and unshift() at the same time it doesn't pick up a change in the array? I tried using $apply() (error already in digest cycle)
There are a few things that could be happening here.
First of all, if onNewTrade is using an external, non-angular, library making xhr requests outside of angular's framework (i.e. not using $http or $resource), you have to call $scope.$apply(function(){ }) around the code you want the scope's digest to know about. That part's not clear from what you've provided. edit: Read more about when to use $scope.$apply
Second, angular's digest phase does a minimum of two passes (first to make changes, second to make sure there are no more changes). It does at most 10 passes by default. If angular evaluates the scope 10 times and it is not consistent, it gives up. see documentation. It does this because you can have multiple watch functions where one watch affects the scope higher in the hierarchy, which makes changes and affects the same watch.. basically causing an evented infinite loop. Do you see a console error about '10 $digest iterations, aborting!' or something similar?
There are a couple of other questionable things:
is onNewRecord asynchronous? If so, I would doubt connectionStopped is being done correctly. You could be returning early. Because you say a breakpoint shows values on unshift, its probably not the cause of this issue (and most likely missing $scope.$apply is the problem), but I'd rethink this code.
Your function is onNewTrade(records), but you log onNewRecord(record). If you have nested variables here, make sure you haven't excluded code that may contain typos (e.g. record instead of records). You might be working on an unexpected object.

Issue with task system - tasks will run exactly twice (re-post once)

I've attempted to write a simple task system for my AVR. The code for this is here. (Sadly, this is also the MWE.)
The basic idea behind the system is that a periodic timer interrupt sets a flag, which the main application loop then checks in order to run a task. The task processing function is re-entrant, so will be executed exactly once per iteration for each pending task:
while (1) {
if (flTask) {
flTask = task_process_next();
}
// Do other awesome stuff in the loop
}
In order to keep the design simple, a task which wants to run periodically is required to re-post itself.
So a simple heartbeat task might be added like this:
task_add(heartbeat_task, 0);
And its code might look like this:
void heartbeat_task(void)
{
task_add(heartbeat_task, 10000); // Re-post task
led_toggle(LEDGreen);
xbee_send_heartbeat(BASE_STATION_ID);
}
My problem is this: each periodic task will run exactly twice.
I have confirmed through toggling pins (as you can see in the code I linked to) that during each task's first and repeat execution the task_add method is called.
However, despite apparently adding the task the second time, it never runs.
I have further tried simplifying the code in task_process_next considerably (including by adding a loop to process all tasks in one call, and by changing the run condition to ignore overflow). Neither of these modifications proved successful.
My question is this: have I messed up some detail of my linked-list implementation which could cause re-posted tasks to be ignored?
In particular, have I accidentally made it so that nodes in the list can be skipped over without being evaluated or run?
I understand that it is difficult to debug this sort of problem without running on the hardware, but I'm hoping that another set of eyes will see what I've missed.
I'm happy to provide any additional information / do any tests which are necessary.
The queue was being corrupted when a task at its end was removed:
if (prev) {
prev->next = task->next;
} else {
tasks.head = task->next;
}
// Adding these lines fixed the problem
if (task == tasks.tail) {
tasks.tail = prev;
}

Resources