Javascript, Node, Promises, and recursion - javascript

I'm having trouble controlling execution flow. This is a follow-on to node.js, bluebird, poor control of execution path and node.js table search fails with promises in use. Judging by console.log print-outs, my recursive routine works great, except that the first call to resolve() (a signal to the nth recursive call) gives the green light to follow-on code that shouldn't get that green light until the first call to the recursive routine calls resolve(). It turns out the first call to the recursive routine delivers the answer I want reported, but by the time it reports it, the follow-on code is no longer listening for it and is running blissfully along with an "undefined" answer. Bad.
My code is much to long to share here. I tried to write a small model of the problem, but haven't found the combination of factors to replicate the behavior.
Sound familiar? How do you keep proper control over Promises releasing follow-on code on time?
I thought maybe the first call to the routine could start an array passed into a Promise.all and later calls would add another entry to that array. I haven't tried it. Crazy?

Without seeing your actual code, we can't answer specifically.
Sound familiar? How do you keep proper control over Promises releasing
follow-on code on time?
The answer is always to not resolve the first promise in the chain until you're ready for things to execute and to structure your promise chain so that dependent things don't get executed until the things they are waiting on have been properly resolved. If something is executing too soon, then you're either calling something too soon or your promise structure is not correct. Without seeing your actual code, we cannot know for sure.
A common mistake is this:
someAsyncOperation().then(someOtherAync()).then(...)
which should be:
someAsyncOperation().then(someOtherAync).then(...)
where you should pass a reference to the next async function rather than calling it immediately and passing its return value.
I thought maybe the first call to the routine could start an array
passed into a Promise.all and later calls would add another entry to
that array. I haven't tried it. Crazy?
You cannot pass an array to Promise.all() and then add things to the array later - that is not a supported capability of Promise.all(). You can chain subsequent things onto the results of Promise.all() or do another Promise.all() that includes the promise from the previous Promise.all() and some more promises.
var someArrayOfPromises = [...];
var pAll = Promise.all(someArrayOfPromises);
var someMorePromises = [...]
someMorePromises.push(pAll);
Promise.all(someMorePromoises).then(...)

Related

Using Angular Http.Get() synchronously

I have a very simple requirement:
I'm writing a authorization service for an Angular site (Angular 7 it makes a difference).
The service needs a "hasPermission" function which takes a user and a resource name. It makes an Http.Get() call to a backend to determine whether or not the user is authorized to access that resource. When, and ONLY WHEN, the data comes back from the Get() call, it returns true or false.
I have been searching the web for about a week trying to figure out how to do it. My problem is that the Http.Get() returns an observable AND THEN CONTINUES. Which means the function returns before it receives the data back on which to make a decision. The same thing if I use the Http.Get().toPromise() - the function continues as soon as the promise is created.
It seems like every "solution" I read is some variant of "return a promise" or "return an observable". But then it's analagous to "It's turtles all the way down" -in this case, it's promises (or observables) all the way up. At some point there needs to be a method that waits for and returns the data, not a promise of the data or an observable of the data.
I need some way to add a "waitForDone" after creation of the observable or promise and before the function returns its value, but from everything I can find, you can't do that in JavaScript because it's single-threaded.
Note, I can't, as some solutions have suggested, "Just put the code after the http.get(...) in a separate function and call it from success callback" because the code to be execute needs to return from this function.
And async/await doesn't do it, because async turns the whole function into a promise, so, even though the await may wait for the Get() to return the data, the function will still have gone on and returned to the caller before it had the data it needed.
It doesn't seem to me that this is an unusual requirement. While it's nice to be able to issue a request then go do something else while you wait for the data to come back, there have to be times when you MUST HAVE the data before you can do anything else.
Any help is appreciated.
You can use the async-await syntax: instead of
get(someArgs).subscribe(doStuff);
you could put async in the function declaration and then go as follows
const someVal = await get(someArgs).toPromise();
doStuff(someVal); // this line won't execute until get() has resolved the promise
But, fundamentally, it is turtles all the way down. It's syntactic sugar atop of the Promise recipe, and that's what it gets transpiled to (if you transpile it).

How to call a promise on Firebase's ''on'' method?

I have a databaseReference.on("child_added", snap => { array.push(snap.val()) }
How do I make a promise, so that any function I call in .then will be initialized AFTER array is filled with database records?
The code above is essentially a for loop, because it iterates through database records and pushes each one of them into an array, so maybe better question would be how to implement a promise on a for loop ?
The best I've found was to return promise with each iteration and then use Promise.all, but I have no clue on how to implement that in this specific example.
on() doesn't generate a promise. And it can't, because the listener you pass to it lasts forever (and continues to deliver changes) until it's removed with off(). This behavior is not compatible with promises. Promises require that some work is executed only once, and once that completes, nothing else should occur that would change the result.
If you want to receive data for a single snapshot at a location, use once() instead of on(). once() returns a promise that's resolved when the data is available. This is fundamentally not compatible with 'child_added' listeners, as they always continually generate results and never terminate with a final result.

JavaScript Promises and race conditions

I just started using Promises in JavaScript using the Q library. I am running into a race condition and am wondering what would be the best way to resolve it.
The problem is that Q always calls the callbacks using process.nextTick() (also mentioned in the Promises/A+ spec) which means that I might miss some state changes in the object in the time between the resolution of the promise and the time the callbacks are called. My concrete problem is that I have an incoming connection and am missing the first messages. Messages are distributed using EventEmitter.
The code looks something like this. It uses the palava-client (but the problem should be universal) and is written in CoffeeScript:
defer = q.defer()
session.on 'peer_joined', (peer) ->
defer.resolve(peer)
return defer.promise
And somewhere else
peer_promise.then (peer) ->
peer.on 'message', (msg) ->
console.log "Message received:", msg
The first messages sometimes are lost because they got emitted before the promise ever got notified. The problem does not occur using only EventEmitter and Callbacks because the callbacks are always called immediately blocking the JavaScript Thread from handling the incoming messages.
The following code never misses messages:
session.on 'peer_joined', (peer) ->
peer.on 'message', (msg) ->
console.log "Message received:", msg
Do you see any way I can solve the problem using promises? I really would like to keep using them in my abstraction layer to ensure that only one peer is accepted. Is there any other way to avoid such race conditions?
As someone who usually promotes using promises, my suggestion is:
Do not use promises here
Promises represent one time events. They are an abstraction over values, one a promise changes its state it can no longer be changed. A promise starts off as pending and changes state once to either fulfilled or rejected.
You are facing a scenario where you have many users, each user joins and needs to add events, the users might 'go away', your scenario simply doesn't describe the same linear flow promises excel at. Promises are useful for a certain scenario - they are not for every concurrency problem. Using an event-emitter here is perfectly appropriate.
Your case (a user joining) does not really represent a resolved proxy operation. The code that "doesn't miss messages" is indeed more correct.
If you still choose to use promises here
There are a few things you can do:
You can use Q's progression events and add a progress handler in the creation phase. Note that Kris (Q's author) has called progression broken, and it is being removed in the next version of Q. I recommend against it.
You can wrap the message callback to only fire once a handler has been attached - accumulate items fired with a handler when it is created (in an array) and then trigger them all when the message handler is added (after you resolve, in a .then on the deferred you return.

What happens to a jQuery promise after it is done being used?

It seems that there is no way for jQuery to know when your app is done using a promise. Since memory is managed in js, I presume that the promise continues to exist until all references to it are gone. Specifically, it will exist indefinitely until it is resolved AND the code that created or used it has finished exiting (functions returned etc). At which point it will be garbaged collected.
Can anyone verify my assumptions? Or add other thoughts to this?
Understanding the underlying mechanics has some important connotations; memory leaks, potential caching opportunities (via persisting promises after they have been resolved), etc. My next step is to dive into the jQuery source, but I was hoping for some additional guidance before starting that.
If there are no references to a resolved promise, it will (eventually) be disposed. Otherwise, it will be kept in memory in case anyone wants to access its value.
Promises are no different here from any other object in this case.
Promises are only removed in one case, if the progress is done.
js source
.done( updateFunc( i, resolveContexts, resolveValues ) )
...->
deferred.resolveWith( contexts, values );
To note, resolveWith is part of jQuery convention to use what they call a tuple, resolve in this case, suffixed with "With" in order to essentially issue a callback to deferred.resolve. This essentially calls the original callback using the same context as the deferred object.
Internally when a callback from a list is fired, jQuery will remove that from the list of callbacks held for that list.
Thus, the only way a promise is resolved, is by being done. There is no timing which monitors it.
The promise will either be attached to the target if one is passed in the jQuery constructor, or will be attached to a new instance of jQuery. This will be the lifetime of the list which holds these deferred callback lists.
As with any other garbage collection, this lifetime will be browser dependent (IE sometimes does interesting things).

How to think when working with promises

I'm working for the first time with async programming, specifically with promises in Javascript and I'm really confused with it. I'm still thinking like we do in C, PHP, C# and so on where for each step the next one can be sure of it's completion. This is easy to work, because if we have a code like that (in C# for example)
IEnumerable<Page> pages = pagesRepository.getAll();
we can be sure in the next line that all pages are available for us to use in the pages object. This makes life easier, because we can already do work with that data properly.
Now, in JS with promises we would have something like
var pages = dataService.getPages();
and this would not return the data, but just a promise which is very different. Of course we can add a callback with then but I'm getting confused, because somewhere else in my code I might need to reference this variable, and I cannot be sure when the callback will be called.
So how do we think when we deal with those things? Is there some tutorial or some videos out there that show in detail how to work with async programming with promises in JS?
Of course we can add a callback with then but I'm getting confused, because somewhere else in my code I might need to reference this variable, and I cannot be sure when the callback will be called.
You don't need to.
The "somewhere else code" will use .then() and yield a new promise for its result, relying on the pages promise. You can easily map the results, or chain other asynchronous tasks. Whenever you need to know about the timing of callbacks because of multiple dependencies, you should use your library's methods for composing promises, like all().
So how do we think when we deal with those things?
Think functional!
Every task in your program should explicitly and only depend on its inputs. A function should try to only use its arguments, not any global variables that contain state.
Is there some tutorial or some videos out there that show in detail how to work with async programming with promises in JS?
General Promise Resources in the wiki of the Q library is a very good start.
The simple answer here is that promises are similar to Task asynchronous programming in C#.
However instead of being able to use the 'await' operator, the 'then' function on a promise is analogous to using 'ContinueWith' to chain Tasks in C#.
Callbacks can get complicated to use across scopes, especially with extensive use of nested anonymous functions, so please give promises a go

Categories

Resources