Javascript: Synchronize observable events - javascript

I am using Ionic2 with Meteor. I observe a Cursor, for when it gets added to or updated.
public messages: Mongo.Cursor<Message>;
this.messages.observe({
added: (message) => this.addMessageToLocal(message),
changed: (message) => this.updateMessageToLocal(message)
});
In my case, the added event gets triggered before the changed event. However, they run asynchronously. I would like the event that is triggered first (added) to finish before the next event (changed) starts.
Is this possible?
Thank you
UPDATE
I am thinking of maintaining a flag, that says when one job is busy, and the other one must wait until it is finished. Is this advisable?

In the asynchronous world of javascript you cannot control (much as you would like to) the order of execution.
There are two ways to deal with this
1) Get used to it, and write your code accordingly
2) Do the first thing, and then start the second thing in the callback response for the first thing (although in this case I don't think you can)

Related

wait in while loop for external variable change or event?

I've a question/problem with an whileloop
I need to wait until something changes outside the while loop.
Let's say i have this while loop:
window.changeMe = true;
while(window.changeMe){
}
now i have these two options:
Change the changeMe variable via the Console/JavaScript Execution
Change the changeMe variable via an WebSocket Event
but neither is working, if i change the Variable directly, it is not changed.
If i trigger an WebSocket Event its not getting called.
Maybe its BLOCKED.. so is there any other way to change the variable?
I known i can use await and its already working that way, but the problem is that these functions with while are called via an Addon
and using many await's looks kinda ugly for the addon creator :(
an system with setTimeout & Callbacks are also working but also looks kinda ugly..
Yes, you are correct. Having a infinite while loop will prevent executing any other code from javascript event loop which occupies the main thread.
In order to imitate the same behavior you can implement your own while loop that is friendly to asynchronous events and external code execution. You have to use:
tail recursion in order to minimize the memory footprint,
setTimeout as a mechanism to allow other parts of your code to run asynchronously.
EXAMPLE:
window.changeMe = true;
let stop = setTimeout(() => { console.log("External change stop"); window.changeMe = false; }, 4000)
var whileLoop = () => {
console.log("Inside: ", window.changeMe)
return window.changeMe
? setTimeout(() => { whileLoop(); }, 0)
: false
}
whileLoop()
console.log("Outside: ", window.changeMe)
Here is a fiddle:
https://jsfiddle.net/qwmosfrd/
Here is a setInterval fiddle:
https://jsfiddle.net/2s6pa1jo/
Promise return value example fiddle:
https://jsfiddle.net/0qum6gnf/
JavaScript is single-threaded. If you have while (true) {}, then nothing else outside the while loop can change the state of your program. You need to change your approach. You probably want to set up event listeners instead or put this inside an async function so you can use await to release execution, or some other asynchronous API. But plain vanilla while () {} is synchronous and cannot be affected by other things while it is running.
You can't use a while loop in that way in nodejs.
Nodejs runs your Javascript in a single thread and the overall architecture of the environment is event driven. What your while loop is doing is a spin loop so while that loop is running, no other events can ever run. You have to return control back to the event loop before any other events can run. That means that timers, network events, etc... cannot run while your spin loop is running. So, in nodejs, this is never the right way to write code. It will not work.
The one exception could be if there was an await inside the loop which would pause the loop and allow other events to run.
So, while this is running:
while(window.changeMe){
}
No other events can run and thus nothing else gets a chance to change the changeMe property. Thus, this is just an infinite loop that can never complete and nothing else gets a chance to run.
Instead, you want to change your architecture to be event driven so that whatever changes the changeMe property emits some sort of event that other code can listen to so it will get notified when a change has occurred. This can be done by having the specific code that changes the property also notify listeners or it can be done by making the property be a setter method so that method can see that the property is being changed and can fire an event to notify any interested listeners that the value has changed.

Cloud Function stuck in an infinite loop

exports.addNewValue = functions.database.ref('/path')
.onWrite(event => {
event.data.adminRef.update({"timeSnapshot":Date.now()})})
It appears that Date.now() causes an infinite loop in the function because the following does not:
exports.addNewValue = functions.database.ref('/path')
.onWrite(event => {
event.data.adminRef.update({"timeSnapshot":"newString"})})
How do I fix this?
If you write back to the same location in the database that was previously changed, you can expect this sequence of events:
Function is triggered with the first change from the client
Function writes back to the database
Function is triggered a second time because of the write during step #2
All writes to the database that match the filter path, even those from within the same function, will trigger the function.
In step 3, you need a strategy to figure out if the second function invocation should result in yet another write back to the database. If it does not require another write, the function should return early so that it won't trigger another write. Typically you look at the data in the event passed to the function and figure out if it was already modified the first time. This could involve looking to see if some flag is set in the database, or if the data you modified does not need any more changes.
Many of the code samples provided by the Firebase team do this. In particular, look at text moderation. Also, there is a video that describes the problem and a possible solution. In the end, you're responsible for coming up with the strategy that meets your needs.
I think the following should work fine :-
exports.addNewValue = functions.database.ref('/path/timeSnapshot')
.onWrite(event => { event.data.adminRef.set(Date.now()) })
The logic behind the above is that when you put a trigger function on a higher node (such as /path in your case), then the function would be fired each time a change is made to any of its child nodes (/timestamp in your case) - hence, the infinite loop.
Therefore, as a general practice, for efficiency as well as cost effectiveness, make sure that your trigger function has the lowest possible path node. Flatting out your data really helps in this as well.
If you arrived here having problems with querying try using .once('value') ... it will mean that you only look at the reference point once ... i.e.
ref.orderByChild("isLive").equalTo(true).once("value" , function(snapshot) {
instead of
ref.orderByChild("isLive").equalTo(true).on("value", function(snapshot) {
as the second will have you listening all the time, and when data changes at the ref, the listener will receive the changes and run the code inside your block again

These functions appear to be being executed out of order

The strangest thing just happened to me. I have some javascript that appears to be being executed in the wrong order. This is freaking me out! Observe:
the code
handleKeyDown: function (e) {
console.log("handleKeyDown");
var key = e.which;
var text = this.ui.$input.val();
if (_.isFunction(this[key])) {
// call the appropriate handler method
this[key](text, e);
console.log("before announceEdits");
this.announceEdits();
}
if (key === ENTER || key === ESC) {
console.log("fired field:key:down");
this.trigger("field:key:down", { editable: this, restore: (key === ESC) });
}
},
announceEdits: function () {
console.log("announceEdits");
var edits = this.getEdits();
console.log("edits: %o", edits.data);
console.log("fired field:edits");
this.trigger("field:edits", edits);
},
/* gather all the existing taggies */
getEdits: function () {
var data = this.$taggies().map(function (index, taggy) {
return $(taggy).data("value");
}).toArray();
var edits = {
attribute: "tags",
data: data
};
return edits;
},
When I run this code, the functions appear to be being executed out of order. This is the output in firefox's console of the above code:
the output
Notice that we get before announceEdits long before we get announceEdits, which is the first line in the annouceEdits function... my understanding of the world leads me to believe this is wrong.
what I've done
Now, I have considered the following:
The console statements could be being buffered or some such, causing them to appear out of order.
This could have something to do with the way MarionetteJS handles events.
Believing that this might be evented weirdness, I tried removing the calls to trigger (just by commenting out the lines that trigger the events). After removing the triggers, the log statements still appear out of order. So it doesn't seem to be cause by MarionetteJS's implementation of events (which is to say, BackboneJS's implementation of events ^o^//).
I'm also lead to believe that this isn't a log statement buffer issue, because the events are themselves handled out of order (i.e. the data I expect to have after the handling of the first event is not in order by the time the second event is handled). This causes the code to "not work" in the way I would like (however, see below).
In my explorations, I've tried to narrow things down a bit. I modified the code thusly, in order to simplify the code:
if (_.isFunction(this[key])) {
// call the appropriate handler method
this[key](text, e);
console.log("before announceEdits");
console.log("announceEdits");
var edits = this.getEdits();
console.log("edits: %o", edits.data);
console.log("fired field:edits");
this.trigger("field:edits", edits);
}
This way I am not descending into a subroutine. Running this code, the console statements appear in the right order. What's more interesting is that, in this case, the events are also fired and handled in the order I expect! This code works, but the one with the subroutine doesn't.
I tried to create a fiddle of this code, but jsfiddle doesn't appear to like Backbone (I tried including the library as an external library, but that didn't seem to work). I did create this fiddle, just to reassure myself that somewhere in the world there is still a rock of normality.
update: I changed the fiddle so that the main function is itself a handler. Everything still works fine in the fiddle.
how I thought the world worked
Functions create stack-frames that execute to completion. If a function calls another function, a new stack-frame is pushed to the stack. If a function triggers an event, it creates a message, which is pushed onto a message queue. Whenever (and I'm unclear on this) the stack is empty, the next message in the queue is popped off, and all handlers for this message are then invoked.
In this model, without question, the events should happen in the order that I expect (the order from the second listing). We should first descend into announceEdits, push the field:edits message to the queue, and then pop back out and push the field:key:down message. Then the handlers for field:edits should run, and finally those for field:key:down.
the question
Is there anything that could be causing these functions to be being executed out of order? Or more likely: is there anything that could be causing these functions to appear to be being executed out of order?
If this is a problem with my understanding: where did I go wrong?
If this ends up being something that was caused by a typo, please bear in mind that we are all programmers, and that we have all torn out hair and bellowed at shadows at times.
lesson
Sleep on it. In the heat of the moment, every bug is a mysterious force from another world. Step back from the problem, start from the beginning. Everything will become clear.
I came in this morning, put a debugger at the beginning of handleKeyDown and immediately saw what was wrong. It isn't in the code I gave above, naturally, and it isn't a problem with how javascript works (clearly!). I had wrapped announceEdits in a debounce earlier, to relieve a head-ache I had been having.
Good news is, my understanding of how event handling works does not appear to be in question.

What are the proper use cases for process.nextTick in Node.js?

I have seen process.nextTick used in a few places and can't quite tell what it's being used for.
https://github.com/andrewvc/node-paperboy/blob/master/lib/paperboy.js#L24
https://github.com/substack/node-browserify/blob/master/index.js#L95
What are the main/proper use cases of process.nextTick in Node.js? The docs basically say it's a more optimized way of doing setTimeout, but that doesn't help much.
I used to do a lot of ActionScript, so the idea of "waiting until the next frame" to execute code makes sense on some level - if you're running an animation you can have it update every frame rather than every millisecond for example. It also makes sense when you want to coordinate setting a bunch of variables - you change the variables in frame 1, and apply the changes in frame 2. Flex implemented something like this in their component lifecycle.
My question is, what should I be using this for in server-side JavaScript? I don't see any places right off the bat where you'd need this kind of fine-tuned performance/flow control. Just looking for a point in the right direction.
process.nextTick puts a callback into a queue. Every callback in this queue will get executed at the very beginning of the next tick of the event loop. It's basically used as a way to clear your call stack. When the documentation says it's like setTimeout, it means to say it's like using setTimeout(function() { ... }, 1) in the browser. It has the same use cases.
One example use case would be, you create a constructor for some object that needs events bound to it. However, you can't start emitting events right away, because the code instantiating it hasn't had time to bind to events yet. Your constructor call is above them in the call stack, and if you continue to do synchronous things, it will stay that way. In this case, you could use a process.nextTick before proceeding to whatever you were about to do. It guarantees that the person using your constructor will have time enough to bind events.
Example:
var MyConstructor = function() {
...
process.nextTick(function() {
self._continue();
});
};
MyConstructor.prototype.__proto__ = EventEmitter.prototype;
MyConstructor.prototype._continue = function() {
// without the process.nextTick
// these events would be emitted immediately
// with no listeners. they would be lost.
this.emit('data', 'hello');
this.emit('data', 'world');
this.emit('end');
};
Example Middleware using this constructor
function(req, res, next) {
var c = new MyConstructor(...);
c.on('data', function(data) {
console.log(data);
});
c.on('end', next);
}
It simply runs your function at the end of the current operation before the next I/O callbacks. Per documentation you can use it run your code after the callers synchronous code has executed, potentially if you can use this to give your API/library user an opportunity to register event handlers which need to be emitted ASAP. Another use case is to ensure that you always call the callbacks with asynchronously to have consistent behaviours in different cases.
In the past process.nextTick would be have been used provide an opportunities for I/O events to be executed however this is not the behaviour anymore and setImmediate was instead created for that behaviour. I explained a use case in the answer of this question.
"Every callback in this queue will get executed at the very beginning of the next tick of the event loop" is not correct. Actually, nextTick() runs right after completing the current phase and before starting the next phase. Minute details are important!
A function passed to process.nextTick() is going to be executed on the current iteration of the event loop, after the current operation ends. This means it will always execute before setTimeout and setImmediate.
Understanding setImmediate()

Do I need to be concerned with race conditions with asynchronous Javascript?

Suppose I load some Flash movie that I know at some point in the future will call window.flashReady and will set window.flashReadyTriggered = true.
Now I have a block of code that I want to have executed when the Flash is ready. I want it to execute it immediately if window.flashReady has already been called and I want to put it as the callback in window.flashReady if it has not yet been called. The naive approach is this:
if(window.flashReadyTriggered) {
block();
} else {
window.flashReady = block;
}
So the concern I have based on this is that the expression in the if condition is evaluated to false, but then before block() can be executed, window.flashReady is triggered by the external Flash. Consequently, block is never called.
Is there a better design pattern to accomplish the higher level goal I'm going for (e.g., manually calling the flashReady callback)? If not, am I safe, or are there other things I should do?
All Javascript event handler scripts are handled from one master event queue system. This means that event handlers run one at a time and one runs until completion before the next one that's ready to go starts running. As such, there are none of the typical race conditions in Javascript that one would see in a multithreaded language where multiple threads of the language can be running at once (or time sliced) and create real-time conflict for access to variables.
Any individual thread of execution in javascript will run to completion before the next one starts. That's how Javascript works. An event is pulled from the event queue and then code starts running to handle that event. That code runs by itself until it returns control to the system where the system will then pull the next event from the event queue and run that code until it returns control back to the system.
Thus the typical race conditions that are caused by two threads of execution going at the same time do not happen in Javascript.
This includes all forms of Javascript events including: user events (mouse, keys, etc..), timer events, network events (ajax callbacks), etc...
The only place you can actually do multi-threading in Javascript is with the HTML5 Web Workers or Worker Threads (in node.js), but they are very isolated from regular javascript (they can only communicate with regular javascript via message passing) and cannot manipulate the DOM at all and must have their own scripts and namespace, etc...
While I would not technically call this a race condition, there are situations in Javascript because of some of its asynchronous operations where you may have two or more asynchronous operations in flight at the same time (not actually executing Javascript, but the underlying asynchronous operation is running native code at the same time) and it may be unpredictable when each operation will complete relative to the others. This creates an uncertainty of timing which (if the relative timing of the operations is important to your code) creates something you have to manually code for. You may need to sequence the operations so one runs and you literally wait for it to complete before starting the next one. Or, you may start all three operations and then have some code that collects all three results and when they are all ready, then your code proceeds.
In modern Javascript, promises are generally used to manage these types of asynchronous operations.
So, if you had three asynchronous operations that each return a promise (like reading from a database, fetching a request from another server, etc...), you could manually sequence then like this:
a().then(b).then(c).then(result => {
// result here
}).catch(err => {
// error here
});
Or, if you wanted them all to run together (all in flight at the same time) and just know when they were all done, you could do:
Promise.all([a(), b(), c()])..then(results => {
// results here
}).catch(err => {
// error here
});
While I would not call these race conditions, they are in the same general family of designing your code to control indeterminate sequencing.
There is one special case that can occur in some situations in the browser. It's not really a race condition, but if you're using lots of global variables with temporary state, it could be something to be aware of. When your own code causes another event to occur, the browser will sometimes call that event handler synchronously rather than waiting until the current thread of execution is done. An example of this is:
click
the click event handler changes focus to another field
that other field has an event handler for onfocus
browser calls the onfocus event handler immediately
onfocus event handler runs
the rest of the click event handler runs (after the .focus() call)
This isn't technically a race condition because it's 100% known when the onfocus event handler will execute (during the .focus() call). But, it can create a situation where one event handler runs while another is in the middle of execution.
JavaScript is single threaded. There are no race conditions.
When there is no more code to execute at your current "instruction pointer", the "thread" "passes the baton", and a queued window.setTimeout or event handler may execute its code.
You will get better understanding for Javascript's single-threading approach reading node.js's design ideas.
Further reading:
Why doesn't JavaScript support multithreading?
It is important to note that you may still experience race conditions if you eg. use multiple async XMLHttpRequest. Where the order of returned responses is not defined (that is responses may not come back in the same order they were send). Here the output depends on the sequence or timing of other uncontrollable events (server latency etc.). This is a race condition in a nutshell.
So even using a single event queue (like in JavaScript) does not prevent events coming in uncontrollable order and your code should take care of this.
Sure you need. It happens all the time:
<button onClick=function() {
const el = document.getElementById("view");
fetch('/some/api').then((data) => {
el.innerHTML = JSON.stringify(data);
})
}>Button 1</button>
<button onClick=function() {
const el = document.getElementById("view");
fetch('/some/other/api').then((data) => {
el.innerHTML = JSON.stringify(data);
})
}>Button 2</button>
Some people don't view it as a race condition.
But it really is.
Race condition is broadly defined as "the behavior of an electronic, software, or other system where the output is dependent on the sequence or timing of other uncontrollable events".
If user clicks these 2 buttons in a brief period, the output is not guaranteed to depend of the order of clicking. It depends on which api request will be resolved sooner. Moreover, the DOM element you're referencing can be removed by some other event (like changing route).
You can mitigate this race condition by disabling button or showing some spinner when loading operation in progress, but that's cheating. You should have some mutex/counter/semaphore at the code level to control your asynchronous flow.
To adapt it to your question, it depends on what "block()" is. If it's a synchronous function, you don't need to worry. But if it's asynchronous, you have to worry:
function block() {
window.blockInProgress = true;
// some asynchronous code
return new Promise(/* window.blockInProgress = false */);
}
if(!window.blockInProgress) {
block();
} else {
window.flashReady = block;
}
This code makes sense you want to prevent block from being called multiple times. But if you don't care, or the "block" is synchronous, you shouldn't worry. If you're worried about that a global variable value can change when you're checking it, you shouldn't be worried, it's guaranteed to not change unless you call some asynchronous function.
A more practical example. Consider we want to cache AJAX requests.
fetchCached(params) {
if(!dataInCache()) {
return fetch(params).then(data => putToCache(data));
} else {
return getFromCache();
}
}
So happens if we call this code multiple times? We don't know which data will return first, so we don't know which data will be cached. The first 2 times it will return fresh data, but the 3rd time we don't know the shape of response to be returned.
Yes, of course there are race conditions in Javascript. It is based on the event loop model and hence exhibits race conditions for async computations. The following program will either log 10 or 16 depending on whether incHead or sqrHead is completed first:
const rand = () => Math.round(Math.random() * 100);
const incHead = xs => new Promise((res, rej) =>
setTimeout(ys => {
ys[0] = ys[0] + 1;
res(ys);
}, rand(), xs));
const sqrHead = xs => new Promise((res, rej) =>
setTimeout(ys => {
ys[0] = ys[0] * ys[0];
res(ys);
}, rand(), xs))
const state = [3];
const foo = incHead(state);
const bar = sqrHead(state);
Promise.all([foo, bar])
.then(_ => console.log(state));

Categories