I've been asked to help write some server-side scripts that update calendars, contacts, e-mail and other company services from other internal services for compliance reasons. The code needs to access the LDAP server, an SQL database and e-mail server, compile and merge information in a peculiar way and then go through information in the calendars, contacts and update those depending on what's there and in the LDAP/SQL databases. This needs to be done a couple of times a day, so performance isn't particularly important.
I wanted to try to use node.js for this and after spending a few days with it, I'm having second thoughts as to whether node.js is the right tool to do this. I'm an old school programmer, have C, C++, Unix, SQL, LDAP, TCP/IP in my small finger but I've learned JavaScript/Node.js in a few days out of curiosity.
I use LDAP, SQL and CalDav/CardDAV modules from npm. These are based on Promises.
Thanks to promises, the code is super ugly, unreadable and buggy if there's any kind of network problem. Things that are very easy in classic language such as C or Java are suddenly a massive headache, such as the fact that (say) LDAP information will arrive at a later stage, but there's no point in async operations as nothing can be done in parallel while waiting for those. This pattern repeats itself throughout the code - async operations complicating matters incredibly for zero benefit. It's incredibly difficult to calculate any sort of aggregate values and apply them elsewhere when using these async functions.
My question is this: is there a simple way to invoke async functions that will simply return the value instead of invoking callbacks?
in javascript - no. Waiting async call to complete would block the only thread and so would stop all the work, and so such waiting is not implemented.
But there exists async/await mechanism - syntactic sugar over asynchronous calls, which mimics synchronous calls.
First of all, the vast majority of I/O calls in Node.js are asynchronous. So if you're totally uncomfortable with this, it may not be the right fit for what you're doing.
It is a (IMHO) brilliant language, and you'll find it more comfortable to use as you get used to it.
However, you can write code using Promises that looks very much like synchronous code using the async/await syntax. I find this much easier to deal with compared to using lot's of .thens and .catch.
You can also use try and catch in this context and it will work as you would expect.
This makes for much cleaner, more readable code.
Most Node.js modules support Promises, for those that don't you can often convert functions to returning a Promise rather than expecting a callback to be passed.
NB: Don't forget to await calls to async. functions. I find this is one of the most common errors one makes when using this syntax.
For example:
function callApi() {
return new Promise(resolve => setTimeout(() => resolve({ status: 'ok'}), 500))
}
async function testApi() {
try {
console.log("callApi: Calling function...");
let result = await callApi();
console.log("callApi result:", result);
} catch (err) {
console.error("callApi: Error:", err.message);
}
}
testApi();
Then a further example to show catching an error (say the api fails for some reason):
function callApi() {
return new Promise((resolve, reject) => setTimeout(() => reject(new Error("Api error")), 500))
}
async function testApi() {
try {
console.log("callApi: Calling function...");
let result = await callApi();
console.log("callApi result:", result);
} catch (err) {
console.error("callApi: Error:", err.message);
}
}
testApi();
Related
Updated below...
So this is a random question that came about from a discussion over what I consider the over usage of await in projects at work...
Not sure why I never tried it until now, other than the fact that it's weird and random, but the fact it does work just makes me wonder...how?
The .Result usage was only used to get the responseMessage. I know that is blocking and no bueno and it is for demo purposes only...
So this endpoint works fine...nothing is awaited
[HttpGet("kitteh")]
public Task<string> GetCatFact()
{
var client = new HttpClient();
var res = client.GetAsync("https://catfact.ninja/fact").Result;
return res.Content.ReadAsStringAsync();
}
There's obviously something in the default ASP.NET pipleline that ultimately unwraps the task in order to return the result...but where...or how?
Is this "less efficient" than awaiting in the endpoint itself as the magic taking place behind the scenes is ultimately just blocking to get the result of the returned task?
Updated
So, I am still skeptical and don't think the answer is as easy as "yes it is blocking" or "not it is not blocking" unless there's some legit proof or something to indicate one way or the other. I tried digging through the code myself, and I still don't have a solid answer but...I do know more than I did before...
I simplified the endpoints I have been testing this with...
[HttpGet("taskstring")]
public Task<string> TaskString()
{
return Task.FromResult("Where does this block?");
}
[HttpGet("asyncstring")]
public async Task<string> AsyncString()
{
return await Task.FromResult("This definitely doesn't block");
}
I stepped through a bunch of code and ultimately landed on ObjectMethodExecutor and AwaitableObjectResultExecutor which sparked some interest.
What appears to happen for both the endpoint versions above is the same or nearly the same, at least the execution of these two endpoints and the code covered below. There's a boatload that goes on during this and even though the rider debugger is great, it's not possible to see a lot of the values while debugging due to "Evaluation is not allowed: The thread is not at a GC-safe point".
When the endpoint is called but prior to the endpoint beginning execution...
ObjectMethodExecutor.ctor is called
This does a lot of inspection of the endpoint to determine a bunch of things
One of the checks is to is determine if the method is "async" and it ultimately calls AwaitableInfo.IsTypeAwaitable to check for the required methods/properties and interfaces to ensure it is
If it is, which in the case of returning Task of string it is, makes sense given the above info
ObjectMethodExecutor.GetExecutorAsync() is called
AwaitableObjectResultExecutor.Execute is then called
this type inherits ActionMethodExecutor which overrides the Execute method
executor.ExecuteAsync(executor type of ObjectMethodExecutorAwaitable) is then called, and awaited
this returns a result of type object, boxing yeah I know
The endpoint then actually executes and returns to AwaitableObjectResultExecutor.Execute
the result is then passed to ConvertToActionResult along with the return type, the T of Task of T and the mapper implementation
the mapped ActionResult is then returned
So...I'm still not certain 100% either way but there is a lot of effort put into inspecting the endpoint that is being called and determining if it's async or not, which would make it seem logical to think this is an attempt to avoid something...maybe blocking?
So...does it block...maybe? Seeing that there is an await from the indirect caller of the endpoint, I'd lean towards, no...but it seems really difficult to say still.
What I do now know is...
It definitely does await the endpoint call, albeit indirectly
It converts the Task of string return type to an IActionResult
An async and task only version seem to follow the exact some flow shown above
A non async version does not
So, based on all of that...#Phil's answer seems to be pretty spot on with what I found...
"The framework supports asynchronous controller actions. In order to do so, it would need to inspect the return value of your methods. If the method returns a Task, it will ultimately await on the result before responding.
Even if your action itself does all the awaiting, it still has to return a Task so the caller will still wait (the alternative being some ugly blocking code)."
Thanks to all for participating in an extremely random question that doesn't hold much value to truly understand
Your assumption here is basically correct...
There's obviously something in the default ASP.NET pipleline that ultimately unwraps the task in order to return the result
The framework supports asynchronous controller actions. In order to do so, it would need to inspect the return value of your methods. If the method returns a Task, it will ultimately await on the result before responding.
Even if your action itself does all the awaiting, it still has to return a Task so the caller will still wait (the alternative being some ugly blocking code).
As has been pointed out in some other posts, there are some performance improvements to be had by not awaiting a returned Task so I would write your action as
public async Task<string> GetCatFact()
{
var client = new HttpClient();
var res = await client.GetAsync("https://catfact.ninja/fact");
return res.Content.ReadAsStringAsync(); // no await
}
Your controller handles waiting for the remote response but delegates waiting for the content stream to the caller.
There's obviously something in the default ASP.NET pipleline that ultimately unwraps the task in order to return the result...but where...or how?
ASP.NET asynchronously waits for your task to complete, and then it sends the HTTP response based on the result of the task. It's logically similar to await: an asynchronous wait.
Is this "less efficient" than awaiting in the endpoint itself as the magic taking place behind the scenes is ultimately just blocking to get the result of the returned task?
Yes. It is less efficient to block.
ASP.NET doesn't block; it asynchronously waits. Blocking ties up a thread. So when the code calls .Result, it will be using a thread just to wait for that HttpClient call to complete.
The proper solution is to keep async and await:
[HttpGet("kitteh")]
public async Task<string> GetCatFact()
{
var client = new HttpClient();
var res = await client.GetAsync("https://catfact.ninja/fact");
return await res.Content.ReadAsStringAsync();
}
This way, while the GetAsync is in progress, the thread is yielded back to the ASP.NET runtime and is available for handling other requests, instead of being blocked waiting for the GetAsync to complete.
More information: Task<string> is part of the method signature. ASP.NET has special understanding of the Task<T> type and knows to asynchronously wait for it. async is not part of the method signature. ASP.NET knows whether your method returns Task, but it has no idea whether it's async (and doesn't care). So, in some situations, it's OK to elide the keywords (as described on my blog, but only when the method implementation is trivial. If there's any logic in the method, keep the async and await.
What is the advantage of using express error handler instead of handling the errors on the routes as they come as shown below. I am starting an open source project and I wanted to go with the best practices.
register: async function(req, res, next, error ){
User.findOne({username: req.body.username}, async function(err, __user){
try {
if(__user)
throw (
{
"type":"Registration Error",
"details" : `The username "${__user.username}" is already taken. Try another one.`
}
)
} catch(err) {
return res.status(500).json( {"error":{"type":err.type, "details":err.details}} )
}
Are there scenarios where it is better to use one way over the other?
To see the code above in its full context click here
From this article there are definately benefits of using express error handler.
For instance:
you can manage all your errors from one place
You write less code.
You can group errors and manage them depending on their types.
You can get more info from the article. :)
Using the built-in error handler in Express has a number of benefits:
It centralizes error handling in a single place, which makes it easier to maintain and update your error handling logic.
It allows you to handle errors in a consistent way throughout your application, rather than having to repeat error handling logic in multiple places.
It can help improve the readability and maintainability of your code by abstracting the error handling logic away from the main route handling logic.
In essence, instead of having try/catch and repeated return res.status(500).json() logic all throughout your routes, you handle errors in one place and only have to throw in said routes.
I'm building a site with Nuxt/Vue, and it's using a GraphQL backend API. We access this using the Apollo module for Nuxt.
In a page component, you can do this (I think this is called a Smart Query, but I'm not sure):
apollo: {
pages: {
query: pagesQuery,
update(data) {
return _get(data, "pageBy", {});
}
},
}
}
But you can also do the query like this I think, using the Nuxt asyncData hook:
asyncData(context) {
let client = context.app.apolloProvider.defaultClient;
client.query({query, variables})
.then(({ data }) => {
// do what you want with data
});
}
}
I'm not sure what the difference is between these two ways, and which is better. Does anyone know? I couldn't find an explanation in the docs anywhere.
Yeah, good question. The code you have shown at the top is indeed called a Smart Query. In fact
Each query declared in the apollo definition (that is, which doesn't
start with a $ char) in a component results in the creation of a smart
query object.
A nuxt project using the #nuxtjs/apollo module can use these out of the box. The beauty of the smart query is the options that it comes with and one of these is the 'prefetch' option. This, as it sounds, allows prefetching and is by default set to true. It can also accept a variables object or a function. You can see the docs here.
This means that the outcome of a smart query or an asyncData query will essentially be the same. They should be resolved in the same timeframe.
So why choose one or the other? This would probably be down to preference, but with all the options that a smart query allows you can do a lot more, and you can include subscriptions which might not be possible in asyncData.
More about smart queries here.
In asp.net core ViewComponent we have to implement logic in an InvokeAsync method that returns an IViewComponentResult. However I do not have any async logic to perform inside the invoke method. So based on SO post here I have removed the async qualifier and just return Task.FromResult
public Task<IViewComponentResult> InvokeAsync(MyBaseModel model)
{
var name = MyFactory.GetViewComponent(model.DocumentTypeID);
return Task.FromResult<IViewComponentResult>(View(name, model));
}
and then in View ( since I don't have async I am not using await here)
#Component.InvokeAsync("MyViewComponent", new { model = Model })
However view renders this:
System.Threading.Tasks.Task1[Microsoft.AspNetCore.Html.IHtmlContent]`
You must await the Component.InvokeAsync. The fact that your method doesn't do anything async doesn't matter. The method itself is async.
However, that's a bit of an oversimplification. Frankly, the ease of the async/await keywords belies how complicated all this actually is. To be accurate, instead of calling these types of methods "async", it's more appropriate to discuss them as "task-returning". A task is essentially a handle for some operation. That operation could be async or sync. It's most closely associated with async, simply because wrapping sync operations in a task would be pretty pointless in most scenarios. However, the point is that just because something must return a task does not also imply that it must be async.
All async does is allow the possibility of a thread switch. In scenarios where there's some operation, typically involving I/O, that would cause the working thread to be idle for some period of time, the thread becomes available to be used for other work, and the original work may complete on a different thread. Notice the use of the passive language here. Async operations can involve no thread switching; the task could complete on the same thread, as if it was sync. The task could even complete immediately, if the underlying operation has already completed.
In your scenario here, you're not doing any async work, which is fine. However, the method definition requires Task<T> as the return, so you must use Task.FromResult to return your actual result. That's all pretty standard stuff, and seems to be understood already by you. What you're missing, I think, is that you're thinking that since you're not actually doing any asynchronous work, it would be wrong to utilize await. There's nothing magical about the await keyword; it basically just means hold here until the task completes. If there's no async work to be done, as is the case here, the sync code will just run as normal and yield back to the calling code when done, However, as a convenience, await also performs one other vital function: it unwraps the task.
That is where your problem lies. Since you're not awaiting, the task itself is being returned into the Razor view processing pipeline. It doesn't know what to do with that, so it does what it does by default and just calls ToString on it, hence the text you're getting back. Unwrapped, you'd just have IViewComponentResult and Razor does know what to do with that.
If your logic performed inside the invoke method is synchronous, i.e., you don't have any await, you have 2 options:
You can define invoke method without async keyword and it should return Task.FromResult<T>
Use public IViewComponentResult Invoke() instead.
I think the async keyword enables the await keyword and that's pretty much about it. Nothing special about async keyword.
On the main thread where your view is getting rendered, since the tag helper method
to invoke a view component Component.InvokeAsync() is awaitable, you do need to put await keyword there to start the task. await examines the view component rendering to see if it has already completed. If it has, then the main thread just keeps going. Otherwise the main thread will tell the ViewComponent to run.
I'm working on a project which has a quite simple endpoint:
app.get('/transactions',
listTransactions(connectionPool),
addUser(connectionPool),
sendTransactions);
We get a list of MySQL rows, merge user-data into the response, and send it back to user. My question is, is there a "commonly accepted" place to store the response of listTransactions (in this case)? Do I store it on the req object?
Here's my take. I think you're abusing middleware in this case. The middleware is better at decoding, authenticating, etc. I think your example has reached the point where it would make a lot of sense to wrap these things in a function like so.
app.get('/transactions', function(req, res, next){
var transactionPromise = listTransactions(connectionPool)
.then(function(transactions){
return listTransactions(transactions, connectionPool);
})
.then(function(listedTransactions){
return addUser(connectionPool);
})
.then(function(addUserResponse){
res.send(addUserResponse);
});
transactionPromise.catch(function(error){
res.status(500).send("Something went wrong: " + error.toString());
}
}
I use promises here, but this could easily be done with something like async as well. This approach does a few things:
Allows you to handle errors at the router level, rather than inside each function. If you think about it, should a function called listTransactions really know how to respond to a server request?
In combination with the first point, it allows for better reusability by removing the dependency on the (req, res, next) signature.
Testability. Now you can test all the individual pieces without a reliance on the previous middleware, or a specific req format.
My 2ยข. Hope it helps!