I'm currently learning Dart, but this is also applicable to what's going on in the JavaScript world right now, and it seems like C# also uses the same pattern.
In Dart, any function that uses await must itself be labeled asynchronous through async as follows:
import "dart:html";
main() async {
var context = querySelector("canvas").context2D;
var running = true;
while (running) {
var time = await window.animationFrame;
...
}
}
This does not make sense to me. If a function is waiting on an asynchronous function to complete, is it not then considered blocking? Why do JS and Dart require it to be labeled asynchronous? Would it not be the opposite?
To me it would make far more sense if the calling function must use the async keyword if it calls any function that also includes it in its definition. In this pattern, await would be used to convert asynchronous functions to synchronous ones.
This way would also avoid duplicate functions, since right now, libraries seem to always have func() and funcSync() or funcAsync().
The basic semantics of async/await are the same across F#, VB, C#, Python, Dart, Hack, and JavaScript. So I think this question has sufficient answers from other languages. But since it has been reopened...
If a function is waiting on an asynchronous function to complete, is it not then considered blocking?
No. Think about it this way:
"asynchronous" means "does not block the calling thread".
"synchronous" means "blocks the calling thread".
In an asynchronous method/function, the method/function can be paused at the await points, but it does not block the calling thread while it is paused. The function runs serially (one statement at a time), but asynchronously (without blocking the calling thread).
To me it would make far more sense if the calling function must use the async keyword if it calls any function that also includes it in its definition.
That's how it already works... await consumes promise/future/task-returning methods/functions, and async marks a method/function as capable of using await.
This way would also avoid duplicate functions
This is not possible with historically-blocking imperative languages. A method/function either blocks the calling thread until it is complete, or it does not. It is either synchronous or asynchronous.
There are some interesting alternative approaches to async methods/functions, though:
Go is not historically blocking; you can think of it as a language where every method/function is potentially asynchronous; doing this in any other runtime would be disastrous, but Go avoids those problems by implementing a strict goroutine system with message passing - no shared memory or threads allowed.
Another example are pure functional languages, where Future is just another monad and requires no special compiler support for async/await keywords.
In Dart async indicates that the code containing await needs to be rewritten.
async/await is just syntactic sugar for the Future.then() base API, and the code is rewritten to this canonical Future based form, before it is compiled and executed.
Therefore await doesn't make code blocking.
There are also other supported markers like *sync and *async for generators.
See also
- Dart async/await internals
- https://www.dartlang.org/articles/language/await-async
I'm not sure what your question has to do with C# but await is a most unfortunate keyword choice in C#. await is more understandable if you read it as resume after or even yield then resume after. When execution encounters await, it suspends the current function, returning to its caller. Once the Task being waited on is done, execution resumes after the await when the caller needs the result (from an await expression of its own).
This is a fundamental misunderstanding of what's going on "under-the-hood", I'm assuming the javascript async/await implementation mirrors (at least conceptually) that of the .NET world (which originated in F#).
Essentially:
A "unit of work" "token" of sorts (in C# a Task in JS a Promise) represents a completion of a task with an option of returning a value.
An "asynchronous" method is marked with async, to indicate to the compiler/interpreter/runtime whatever, that this method will return said token, and will likely consume some as well.
The thingamajig running it all, will (in C#'s case), rewrite the code on the sly to essentially do the following:
Start async method
Do standard normal code
Encounter "token" providing method
Call it, grab token
Setup a place the code can jump back to later
Is the token complete? If so, carry on, If not, set a callback to have the runtime come back to this place when it does
In this expanded context, the keywords make sense:
async(hronous) - A method that does some task that can take an indeterminate amount of time, that can be waited upon.
await - Indicates that instead of just grabbing the token from the async method and doing nothing with it, that you actually want to set up all this ceremony around listening out for when the work is done, and carrying on afterwards.
tl;dr
Just think of async and await as invisible callbacks, async indicates when something can be listened out for, and await is what actually does the listening.
Related
Is there a way to tell if your function is being called synchronously or asynchronously?
For example, if I have a function shown below?
async function callMe() {
console.log("Am I called asynchronously?", callMe.isCalledAsync);
}
callMe(); // false
await callMe(); // true
The use case is I've needed to convert an existing function from sync to async and for testing purposes and because Chrome Debugger is reporting odd results, I want to check from inside the function that it's being called asynchronously. Another use case is if it's a public method than I want to make sure it's called using await.
Chrome Debugger seems to be aware of the await and async as shown in the screenshot below but either the debugger is incorrect or my code is incorrect or the JIT is not processing the calls async because Chrome Debugger is saying that only the first call is async but the recursive calls are not as shown in the image below.
We all know what you are supposed to do. But developers don't always do that; on purpose or on accident. And that's where dev tools like type checkers and autocomplete and intellisense and all development tools help assist and remind developers what's going on and what we might have missed. So having the feature doesn't preclude or prevent writing good code.
No, it's not possible for a function to determine if a caller used the await keyword. It's not even possible for a function to have knowledge from the runtime about whether or not a caller invoked it in an async context.
Because it's a public method I want to make sure it's called using await.
This is the responsibility of a compile-time lint rule, not of a function's runtime implementation. You (or the linter) will need to examine the source/AST of the calling code to make that determination.
I am trying to understand asynchronous programming and came across async/await keywords. I got stuck in understanding use of async/await keywords. I actually looked in two programming languages, JavaScript and C# and found much differences in use of async/await keywords in both languages.
For JavaScript it says:
Async/await makes your code look synchronous, and in a way it makes it behave more synchronously. The await keyword blocks execution of all the code that follows it until the promise fulfills, exactly as it would with a synchronous operation.
Link: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await#:~:text=Async%2Fawait%20makes%20your%20code,would%20with%20a%20synchronous%20operation.
So, its saying that async/await will make the execution synchronous.
For C# it says:
The async keyword turns a method into an async method, which allows you to use the await keyword in its body.
When the await keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete.
Link: https://learn.microsoft.com/en-us/dotnet/csharp/async#:~:text=The%20async%20keyword%20turns%20a,used%20inside%20an%20async%20method.
So, its saying that use of async/await will make the code execution asynchronous.
I would like to ask, is there really a difference between the use of async/await keywords in JavaScript and C#?
Or,
Is something missing in above statements?
Javascript docs says 'it makes your code look synchronous', it doesn't say 'it makes your code synchronous'.
In terms of behavior there's no difference between javascript and c# in async/await.
async keyword denotes that there's an asynchronous operation in this method.
await keyword helps making a CPS (continuation passing style) coding into a code that looks like synchronous. CPS is similar to using then() in javascript after promises or using ContinueWith() in C# Tasks.
Any code before 'await' is running synchronously under current thread. When execution reaches to 'await', the awaited operation starts under a new thread (not necessarily a new thread, but suppose a new thread), hence an asynchronous operation starts, and current thread is freed. When the awaited operation ends, execution returns to the point it left off in the 'await' keyword and continues.
The internal working of javascript and C# are different.
Javascript is event-driven. There is a main event loop and a single thread in javascript. When the awaited operation finishes, an event is raised under the hood and the main single thread continues executing of the async function where it was left off.
In C# there's no event loop or a single thread. We either should use manual threads and explicitly wait and join them after they did their job, or we should use something like async/await that manages thread and continuation management on behalf of us. Using TPL which C#'s async/await internally uses that, continuation of an async code is passed to another task using callbacks.
Anyhow, 'await' keywrods turns a complicated chain of nested then() -js- or ContinueWith() - c#- into a simple beautiful code that looks like a normal -synchronous- code.
function doSomethingCPS() {
asyncOperation1()
.then(r1 => { consume(r1); return asyncOperation2() })
.then(r2 => { consume(r2); return asyncOperation3() })
.then(r3 => { consume(r3); })
}
async function doSomethingAsync() {
var r1 = await asyncOperation1();
consume(r1);
var r2 = await asyncOperation2();
consume(r2);
var r3 = await asyncOperation3();
consume(r3);
}
The two codes are equivalent. But, it's clear that the latter is much more simpler and easier to read.
There's a difference between thread management in javascript and c#.
As it is said, in javascript there's only one thread. If it blocks for any reason, the page will block. It's when browsers show 'The page is not responding' or 'There is a javascript code in this page that blocks the page' message after 20-30 seconds.
In HTML5 worker threads were introduced that helps to employ a real separate thread. It's another topic though.
You might ask if there's only one thread in javascript, how on earth can an asynchronous operation work that is said to work under another thread?!
Good question. In javascript although there's only one single thread, there are objects that natively use separate threads. timers - setInterval() and setTimeout()-, XMLHttpObject() and fetch() are good examples in this regard. Thus, in javascript we indeed can have asynchronous code.
One final point is the way C# uses threads. In C#, async/await works using a library named TPL (Task Parallel Library). There is a Task class at the heart of TPL that resembles an asynchronous task.
The real point we should know is that, a Task is equivalent to an async operation, but it does not necessarily mean a Task uses explicitly a separate thread. There's a task scheduler in TPL that controls internal threads usage. If a Task's job is quick, using a separate thread wastes resources, so the task will run under current thread.
The only thing we should know is that a Task is a logical unit of asynchronous code. In fat, Task is introduced to free us of manually thread management which is nearly a low-level code.
Using async/await we are rid of all boilerplate code that are required under the hood to provide asynchronous code. We can focus on our business code instead.
I am not familiar with JavaScript but this statement:
Async/await makes your code look synchronous, and in a way it makes it
behave more synchronously. The await keyword blocks execution of all
the code that follows it until the promise fulfills, exactly as it
would with a synchronous operation.
Sounds pretty much applicable to C# async/await. For both cases your code looks like you execute it synchronously and your execution is sequential. Because in C# when you have code like this:
// ...
await FooAsync();
Console.WriteLine("Await has returned the execution");
It seems as if your execution thread were running FooAsync, and then, the same thread is calling Console.WriteLine. Whereas in reality when the execution thread hits await, it does lots of things behind the scene. Here's a good article about it. But in most of the cases,
When the await keyword is applied, it suspends the calling method and
yields control back to its caller until the awaited task is complete.
The thread that were executing your code will go about his business. And then proceed with Console.WriteLine when FooAsync is complete by another (or the same) thread.
This behavior is enormously helpful when you work with UI threads like in WPF or WinForms applications.
For example, FooAsync is a very heavy method. It does lots of calculations and takes a lot of time to complete. But you're running your code on UI and when a user hits a button, the underlying code is executed by the UI thread. So if you'll be running and waiting FooAsync synchronously like this:
FooAsync().Result;
Your UI would be "freezed" and the user would demise you.
So when you go
await FooAsync();
UI thread "asks" TaskScheduler to run FooAsync by whatever available thread. After the Task is completed, TaskScheduler tries to execute next line:
Console.WriteLine("Await has returned the execution");
by the UI thread again,
exactly as it would with a synchronous operation.
Mainly looking at the FS api, for most functions it seems there are three flavors to choose from:
Synchronous
Asynchronous using callback
Asynchronous using promises
Async is the superior way to use system resources, however, if I'm already inside an async function and am awaiting every call anyway then there shouldn't be any difference between that and just using synchronous calls, right? To me it just seems like a built in await statement.
I don't know how async is implemented in js/node though. Is there any advantage to using async functions if I'm inside an async function to begin with? (excluding scenarios when I'm running async tasks in parallel)
One should decide to use an async function ONLY based on what is going on inside that function, not on who is calling it. The caller does not affect whether a function should be async or not.
Reasons to make a function async:
You have promise-based asynchronous operations inside the function and you wish to use await.
You have promise-based asynchronous operations inside the function and you wish to take advantage of the automatic catching of synchronous exceptions (and conversion to a rejected promise) that might occur before you invoke your asynchronous operations.
And, that's pretty much it for the reasons to use the async keyword in front of a function.
Things that an async function is NOT (or common misconceptions about async functions):
It doesn't magically make blocking code become non-blocking.
It doesn't make the caller run faster.
It doesn't make synchronous code now run in the background asynchronously.
Async is the superior way to use system resources,
Not sure what you mean there. Asynchronous functions allow you to run operations in a non-blocking fashion so that the main thread in Javascript can do other things while the asynchronous operation is running, but that is not something that an async function enables. That's enabled by an asynchronous operation. The two are different.
if I'm already inside an async function and am awaiting every call anyway then there shouldn't be any difference between that and just using synchronous calls, right?
Incorrect. Using await with a function that returns a promise does suspend execution of the current function (returning a promise immediately), but that allows the main Javascript thread to do other things, serve other requests, etc... Using synchronous code would be blocking and would not allow the main thread to do other things, thus ruining the scalability of a server.
To me it just seems like a built in await statement.
Blocking, synchronous code affects everything else that could be running during your operation. It's not the same as using await.
async/await is not equivalent to synchronous execution; it's syntactic sugar to make working with promises easier (indeed, the goal of these keywords is to make promises closer to writing synchronous code from a programming standpoint and therefore more intuitive to use).
async places a task on the event loop which will execute after all synchronous execution pending on the stack finishes. The advantages of this are clear: the process can do work while waiting for resources to be available (opening a file involves a system call, for example, so it makes sense to make this a non-blocking operation).
If you're already inside an asynchronous function, the advantages and drawbacks of asynchronous operations are just the same as they would be anywhere else. In fact, await can only be used in an async function.
I recently programming in Typescript/Javascript from JAVA 8. As soon as I encountered async/await, it reminded me of CompletableFuture. In java, regardless of the return type of a method, I can call someMethodReturningFuture.get() inside a method and can block the execution at will. But in JavaScript why do we need to declare a method as async when we want to block on some other asynchronous method using await? May be there is something so wrong that I am believing till now about Java/CompletableFuture.
Because JS has a synchronous execution model. The resulting behaviour is often described as "single threaded". For sure you could block that "single thread" to wait for the resolution of a promise, but that would block anything², a behaviour that you probably don't want, and thus it is not part of the language.
²: including browser rendering / reacting to the user, as well as the promise resolution itself ...
One could simply encapsulate number of synchronous requests as an asynchronous request.
The "func" parameter within the below code could for example contain multiple synchronous requests in order. This should give you more power over data contrasting the use of the DOM as a medium to act on the data. (Is there another way?, it has been a while since I used javaScript)
function asyncModule(func)
{
"use strict";
var t, args;
t = func.timeout === undefined ? 1 : func.timeout;
args = Array.prototype.slice.call(arguments, 1);
setTimeout(function () {
func.apply(null, args);
}, t);
}
Now something must be wrong with my reasoning because here is what the specs says:
Synchronous XMLHttpRequest outside of workers is in the process of being removed from the web platform as it has detrimental effects to the end user's experience. (This is a long process that takes many years.) Developers must not pass false for the async argument when the JavaScript global environment is a document environment. User agents are strongly encouraged to warn about such usage in developer tools and may experiment with throwing an InvalidAccessError exception when it occurs. # https://xhr.spec.whatwg.org/
I would think you would want to avoid async in requests at all costs and instead wrapp sync requests within async function.
Here is the main question along with the follow up.
Is there something wrong with the example I gave?
If not then:
How is forcing requests to be async the right solution?
It goes without saying that you have freedom to debunk any of my "claims" if they are simply wrong or half truths. I am confused over this, I give you that.
Keep in mind that I am testing javaScript in terminal, not in the browser. I used the webserver within GO programming language and everything seems to be working fine. It is not until I test the code within the browser that I get hint for this spec.
This answer has been edited.
Yes I my reasoning was faulty!
There are two angles to think about.
What does async actually mean in javascript?
Can one async call stall another async call?
Async in javascript doesn't mean script will be running in a interleaved/alternating processes with more then one callstack. It can be more like a global timed defer/postpone command that will fully take over once it get its chance. This means async call can be blocking and the nonblocking "async:true" part is only a "trick" based on how xhttprequest is implemented.
This means encapsulating a synchrounous request within setTimeout could be waiting for a failed request that ends up blocking other unrelated async requests where as "async:true" feature would only execute based on its state value.
This means older browser support requires you to chain requests or to use DOM as a medium when you need to do multiple requests that depend on another..Ugh...
Lucky for us, Javascript has threads now. Now we can simply use threads to get clean encapsulation of multiple correlated requests in sync. (or any other background tasks)
In short:
The browser shouldn't have any problems of running request in sync if it is within a worker. Browsers have yet to become OS, but they are closer.
P.S. This answer is more or less because of trial and error. I made some test cases around firefox and observed async request do halt other async requests. I am simply extrapolating from that observation. I will not accept my own answer in case I am still missing something.
EDIT (Again..)
Actually, it might be possible to use xhttp.timeout along with xhttp.ontimeout. See Timeout XMLHttpRequest
This means you could recover from bad requests if you abstract setTimeout and use it as a schedular.
// Simple example
function runSchedular(s)
{
setTimeout(function() {
if (s.ptr < callQue.length) {
// Handles rescheduling if needed by pushing the que.
s = s.callQue[s.ptr++](s);
} else {
s.ptr = 0;
s.callQue = [];
s.t = 200;
}
runSchedular(s);
}, s.t);
}