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

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.

Related

Can a promise be safely 'swallowed'?

I'm given a promise and am returning it at the end of my function for other code to do more actions after me. A kind of middleware, if you will.
return apiCallPromise;
Lets say for some reason I wish to stop those actions from happening and "swallow" a particular promise. For example by doing the following:
if (promiseShouldBeStopped) return new Promise((resolve) => {})
return apiCallPromise;
This correctly returns a promise, however it never resolves. And so the 'promise chain' has been stopped dead in its tracks.
This seems like an anti-pattern to me as it the promise is left pending forever. Are there any bad effects of this that I should be aware of, or is this a fine technique for "filtering" promises?
Attempt to answer my own question
Does this cause memory issues?
Future code doesn't know that this promise has been filtered out, and so fails to do any "catch" or "finally" cleanup code.
In my case this is not relevant, and I want this code to take care of those errors so that the future code doesn't have to deal with them. (this means I can guarantee that onFulfilled gives the api response, and onRejected only gives an error that is actually unexpected)

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).

Javascript promise that calls "then" immediately

I'm using JavaScript promises extensively in a single-page app I am developing. In certain contexts, I need the "then" method to run synchronously if the promise has already been resolved. For this purpose, I have written a custom promise implementation as a wrapper class, which works fine, but prevents me from using async/await. So I would like to know if there is a way to have both, since it seems to me that async/await is really just syntactic sugar around "then."
The custom promise implementation already implements the PromiseLike TypeScript interface, but apparently async/await always need a native promise. Why?
One possibility I have thought of is to replace the "then" method of a real promise object, instead of building my own wrapper on top. Will this work?
The reason it's important for "then" to be called immediately is that the end of the promise chain is a property of a React component, and the React component displays a loading indicator until the promise is resolved. Without my wrapper, the loading indicator is displayed briefly every time the component updates, which also breaks some user interaction.
Maybe there is a different way to solve this problem. This is my first dive into the world of JavaScript.
I'm using TypeScript and targeting ES6.
but apparently async/await always need a native promise.
No it does not. await works on an object that has a .then method.
Without my wrapper, the loading indicator is displayed briefly every time the component updates, which also breaks some user interaction.
That's not caused by awaiting resolved promises. The .then is executed in a microtask, which means that if the promise really resolved already, the .then will execute directly after the engine executed it's current task, so it gets executed before the browser rerenders.
let promise = Promise.resolve(1);
setTimeout(() => { // Make sure the promise resolved
console.log("sync");
promise.then(() => console.log("then"));
requestAnimationFrame(() => console.log("redraw"));
console.log("sync end");
}, 1000);
You'll see sync, sync end, then, redraw in the console.

Javascript, Node, Promises, and recursion

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(...)

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).

Categories

Resources