Wrap async usage with Meteor - asynchronous

I'm trying to wrap an async function inside my Meteor app.
To make it maximum simple I will try to make a basic example (because all I found was kinda more complex that i actly need).
In my app I am trying to do
console.log("1");
my_func(string_to_display);
console.log("2");
As node is async I get logs 1 and 2 before to see the string i sent to the function.
I tried to call it this way
var my_func_sync = Meteor.wrapAsync(my_fync);
var result = my_func_sync(string_to_display);
Most examples here are more complex, with URLs and calls between server/client/other services. I would like to know if there is a way to wrap a simple function that will only send my string to console. Could anyone give me a most basic example ever please? Would be highly appreciated!

I guess using async await can sort the issue.
async my_funct1(){
console.log("1");
await my_func(string_to_display);
console.log("2");
}
Note that you will need to use async with my_funct1() if you need to use await. This will typically wait for the call to return back from myfunc(string_to_display) to proceed to the next line.

Related

VS code - search for function reference within specific function- macOS

is there any quick way in vs code to search for
method1 referenced inside method2?
I am trying to see if using remote-redux-devtools is useful for my project, and we are using next js which does server side calls via getInitialProps so I am trying to find all references to dispatch inside getInitialProps
rather than search for either term (dispatch or getInitialProps) via command + shift + F individually, i need a more specific search.
in this case I need to search for references to dispatch inside getInitialProps
If we can assume that your getInitialProps functions are of a form similar to this:
static async getInitialProps(ctx) {
const res = await fetch('https://api.github.com/repos/zeit/next.js')
const json = await res.json()
dispatchEvent(event)
return { stars: json.stargazers_count }
}
particularly with respect to the return statement on the final line, then this regex works to distinguish those getInitialProps functions with the sequence dispatch somewhere in that function.
^.*getInitialProps[\s\S]*?\bdispatch[\s\S]*?(return).*\n.*
If you want only dispatch as opposed to dispatchEvent you could use word boundaries around it like \bdispatch\b unless it is used as dispatch( then use \bdispatch( or similar.
See regex101 demo

Why do functions have to be async in order to use await within them?

If I want to await a function, why does that have to be done in an async function only?
If I have this:
Function myFunc() {
return await myOtherFunc();
}
I get an error saying: “await expression is only allowed within an asynchronous function.”
I can understand if myOtherFunc() had to be asynchronous (it doesn't make sense to await an asynchronous function), but why does it care if the calling function is asynchronous or not. You can have a fork in a process within a synchronous function due to a call to an asynchronous function, right? So then why can’t you await that asynchronous function within the synchronous function?
NOTE: my question is NOT a duplicate of Javascript Await/Async Feature - What if you do not have the await word in the function?.
^ that question is asking what happens if await is not used in an async function. I'm asking why the function has to be async in order to use await. My response to DougBug below explains why they are different.
The picture in the following article might help explain it to you a bit.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/index
The basic idea though is that the async keyword allows the function to yield its execution up to a calling function.
As such any function that implements await must be marked async so that it can traverse back up the calling path until the first caller is only waiting on it to complete what it needs to do.

Displaying data from Firebase on load of Ionic app

I'm a beginner in Ionic and Firebase. To learn using ionic+firebase, I'm writing a RandomQuote app to fetch a random entry from Firebase. A reload() method is called when I click a reload button, and the random quote is displayed as expected.
However, I also want the quote to display when the app is loaded, i.e., before I click the reload button. I call the reload() method in the constructor but it doesn't work. I have tried to search for answers on the web but cannot find anything that I could understand. Not sure if I'm searching the wrong keywords or in the wrong domains.
The following is the reload() method that I put in my FirebaseProvider class and called from my home.ts:
reload(){
this.afd.list('/quoteList/').valueChanges().subscribe(
data => {
this.oneQuote = data[Math.floor(Math.random() * data.length)];
}
)
return this.oneQuote;
}
Can anyone give me some hints? Or any pointer to useful books / materials for beginners will also be highly appreciated. Thank you very much.
Data is loaded from Firebase asynchronously. This means that by the time your return statement runs this.oneQuote doesn't have a value yet.
This is easiest to say by placing a few log statements around your code:
console.log("Before subscribing");
this.afd.list('/quoteList/').valueChanges().subscribe(
data => {
console.log("Got data");
}
)
console.log("After subscribing");
When you run this code, the output is:
Before subscribing
After subscribing
Got data
This is probably not what you expected. But it completely explains why your return statement doesn't return the data: that data hasn't been loaded yet.
So you need to make sure your code that needs the data runs after the data has been loaded. There are two common ways to do this:
By moving the code into the callback
By returning a promise/subscription/observable
Moving the code into the callback is easiest: when the console.log("Got data") statement runs in the code above, the data is guaranteed to be available. So if you move the code that requires the data into that place, it can use the data without problems.
Returning a promise/subscription/observable is a slightly trickier to understand, but nicer way to doing the same. Now instead of moving the code-that-needs-data into the callback, you'll return "something" out of the callback that exposes the data when it is available. In the case of AngularFire the easiest way to do that is to return the actual observable itself:
return this.afd.list('/quoteList/').valueChanges();
Now the code that needs the quotes can just subscribe to the return value and update the UI:
reload().subscribe(data => {
this.oneQuote = data[Math.floor(Math.random() * data.length)];
}
A final note: having a reload() method sounds like an antipattern. The subscription will already be called whenever the data in the quoteList changes. There is no need to call reload() for that.

WPF background operations using Asynchronous Workflows

To execute operations on a background thread and avoid blocking the UI in a WPF application, I often find myself writing this pattern:
async {
// some code on the UI thread
let uiThread = SynchronizationContext.Current
do! Async.SwitchToThreadPool()
let! result = // some Async<'t>
do! Async.SwitchToContext uiThread
// do things with the result if it wasn't () all along
}
Am I doing this right at all? Is this idiomatic? Should it be done differently?
If this is correct, of course I would prefer not to have to do it like that all the time - is there a built-in shorter way to achieve the same thing? None of the existing Async functions appears to do something like that.
If not, does it make sense to just turn the above code into a function?
let onThreadPool operation =
async {
let context = SynchronizationContext.Current
do! Async.SwitchToThreadPool()
let! result = operation
do! Async.SwitchToContext context
return result
}
That adds another level of async { } nesting - can this cause issues at "some" point?
What you're doing here definitely makes sense. One useful operation here is Async.StartImmediate, which starts the async workflow on the current thread. If you call this from the UI thread, this guarantees that the workflow will also start on the UI thread and so you can capture the synchronization context inside the workflow.
The other trick is that many built-in asynchronous F# operations automatically jump back to the original synchronization context (those that are created using Async.FromContinuations, including e.g. AsyncDownloadString), so when you're calling one of those, you do not even need to explicitly jump back to the original synchronization context.
But for other asynchronous operations (and for non-async operations that you want to run in the background), your onThreadPool function looks like a great way of doing this.
#random-dev is right capturing the context must happen outside the workflow
let onThreadPool operation =
let context = SynchronizationContext.Current
async {
do! Async.SwitchToThreadPool()
let! result = operation
do! Async.SwitchToContext context
return result
}

angularFire $asObject doesn't push

I am new to firebase and trying to use the $asObject as in the angulerFire doc. Basically, I have profile as follows below. I use $asObject to update the email. However when I use $save(), it replaces the entire profile with only the email, rather than pushing it to the end of list ie it works like set() rather than push(). Is how it is meant to work? how do I only push?
Object
{profiles:
{peterpan:
{name:"Peter Trudy", dob:"7th March"}
}
}
My click function:
$scope.angularObject = function(){
var syncProfile = $firebase(ref.child("profiles").child("peterpan"));
var profileObject = syncProfile.$asObject();
profileObject.email= "peter#peterpan.com";
profileObject.$save();
};
You're looking for $update:
syncProfile.$update({ "email": "peter#peterpan.com" });
Note that $update is only available on $firebase and not on the FirebaseObject that you get back from $asObject. The reason for this is that $asObject is really meant as an object that is bound directly to an angular scope. You're not expected to perform updates to it in your own code.
By the way: if the rest of your code is using AngularFire in a similar way, you might consider dropping AngularFire and using Firebase's JavaScript SDK directly. It is much simpler to use, since it doesn't need to mediate between Firebase and Angular's way of working.

Resources