Determine whether a method is synchronous or asynchronous - javascript

In node.js, is it possible to determine (using a function) whether a method is synchronous or asynchronous?
I'd like to write a function that does the following:
function isSynchonous(methodName) {
//if the method is synchronous, return true. Otherwise, return false.
}

From a language standpoint this is not possible, which I believe llambda's answer proves.
Functions can do things asynchronously but return something synchronously; say, return the number of async tasks that were fired off.
Functions can synchronously return promises... that represent asynchronous information. I would call such a method asynchronous but the language can't really tell that.
In some perverse sense every asynchronous function "returns" something... undefined if nothing else.
From an engineering standpoint:
read the documentation.
If the function accepts a callback, it is likely asynchronous. Look at the function signature.
Read the code.
Use "common sense." If the function does IO and returns a result from IO it must be, in some case, asynchronous. This includes file reading, reading from standard input, saving to a database, and HTTP/AJAX requests. Note streams are often used for this, which represents an asynchronous task, but the callbacks are special.
Furthermore there are functions that mix the two.
function(callback) {
if(ready) {
callback();
}
else {
setTimeout(callback, 5000);
}
}
Arguably this is very evil, and correct practice would be
if(ready) {
process.nextTick(callback);
}
so the function has uniform behavior.
However there is a hacky way to tell if anything asynchronous happened, at least in Node.js. See this discussion.
// untested!! please read the documentation on these functions before using yourself
var work = process._getActiveHandles().length + process._getActiveCallbacks().length;
foo;
var newWork = (process._getActiveHandles().length + process._getActiveCallbacks().length) - work;
if(newWork > 0) {
console.log("asynchronous work took place.");
}
This works because asynchronous work cannot resolve on the same tick, by definition, and because Node.js is single threaded.

You don't necessarily know. A function could even be randomly synchronous or asynchronous.
For example, a function that takes another function could execute that function immediately, or it could schedule to execute it at a later time using setImmediate or nextTick. The function could even randomly choose to call its passed function synchronously or asynchronous, such as:
console.log('Start')
function maybeSynchOrAsync(fun) {
var rand = Math.floor((Math.random() * 2))
if (rand == 0) {
console.log('Executing passed function synchronously')
fun()
console.log('Done.')
} else {
console.log('Executing passed function asynchronously via setImmediate')
setImmediate(fun)
console.log('Done.')
}
}
maybeSynchOrAsync(function () { console.log('The passed function has executed.') });
Further, technically speaking, every function call is synchronous. If you call a function F, and F queues a callback function to be invoked later (using setTimeout or whatever mechanism), the original function F still has a synchronous return value (whether it's undefined, a promise, a thunk, or whatever).

No, that's impossible. The methods aren't just marked synchronous or asynchronous, they either use callbacks or they don't.

Why exactly do you need to know, is the real question.
Having said that; that's possible with the new JS abstractions. Nowadays for the async functions those explicitly defined by a preceding async keyword you can perform a test like;
async function test(){}
var type = Object.getPrototypeOf(test).constructor.name;
console.log(type); // <- 'AsyncFunction'
cool..!
As for the normal functions those happen to return a promise, we must remember that it's just a sync function returning a promise object right away, synchronously. That means you have to check dynamically if a function returns a promise in advance, before invoking the function. I think that takes you to a type level programming adventure which exists in sophisticated languages like Haskell etc.

Related

How To Convert Synchronous Functions To Asynchronous Functions In JavaScript [duplicate]

I was unsure how node.js was able to realize what functions where async and which were not and how to create a custom async function.
Say I wanted to create a custom asynchronous function. I would be surprised if just because I called my last argument to the async function callback or cb that it would just know its an async function:
function f(arg1, callback){
//do stuff with arg1
arg1.doStuff()
//call callback
callback(null, arg1.result());
}
I tried something like that and it did not work async. How do you tell node.js that f is actually async?
NOTE: this answer was written in 2014, before the existence of async function, and before Promises gaining popularity. While the same principles apply as well, I would recommend reading on Promises before trying to get your head around how they relate to "traditional" callback-driven async functions.
To create a function that calls its callback asynchronously, you have to use some platform-provided async primitive (typically IO-related) on it - timers, reading from the filesystem, making a request etc.
For example, this function takes a callback argument, and calls it 100ms after:
function asyncFn(callback) {
setTimeout(() => {
callback();
}, 100);
}
A possible reason for making a function async when it doesn't need to be, is for API consistency. For example, suppose you have a function that makes a network request, and caches the result for later calls:
var cache = null;
function makeRequest(callback) {
if (!cache) {
makeAjax(result => {
cache = result;
callback(result);
});
} else {
callback(cache);
}
}
The problem is, this function is inconsistent: sometimes it is asynchronous, sometimes it isn't. Suppose you have a consumer like this:
makeRequest(result => doSomethingWithResult(result));
doSomethingElse();
The doSomethingElse function may run before or after the doSomethingWithResult function, depending on whether the result was cached or not. Now, if you use an async primitive on the makeRequest function, such as process.nextTick:
var cache = null;
function makeRequest(callback) {
if(!cache) {
makeAjax(result => {
cache = result;
callback(result);
});
} else {
process.nextTick(() => callback(cache));
}
}
The call is always async, and doSomethingElse always runs before doSomethingWithResult.
Only native functions (with access to the event loop) are asynchronous. You would need to call one of them to get asynchronity for your callback. See What is a simple example of an asynchronous javascript function?.
If you aren't using any, there's hardly a reason to make your function asynchronous.

How to know if a Javascript Callback is Synchronous or Asynchronous? [duplicate]

This question already has answers here:
How to identify if a callback is going to be executed synchronously or asynchronously? [duplicate]
(3 answers)
Closed 3 years ago.
Hi! I am learning about callbacks and I understand that callbacks can be either synchronous or asynchronous.
I was reading about callbacks on https://www.w3schools.com/jquery/jquery_callback.asp and was quite confused.
There is this code:
$("button").click(function(){
$("p").hide("slow", function(){
alert("The paragraph is now hidden");
});
});
Can I check if there is a way to know if the above callback is Synchronous or Asynchronous?
I am guessing it is Synchronous above because it has to wait till the "slow" animation is over before the alert comes up. Is it by default in Javascript or Node.js all callbacks are synchronous unless you do something like setTimeOut or process.nextTick?
You have several questions here, so I'll try to answer them one by one:
Is it by default in Javascript or Node.js all callbacks are synchronous unless you do something like setTimeOut or process.nextTick?
In the browser you can kinda have this as the rule of thumb: Only setTimeout, setInterval, requests and events are asynchronous. Other built-in callbacks (like Array.prototype.map) are synchronous.
On Node.js it's more complicated: e.g. you can do file reading both synchronously and asynchronously. Then you just need to know that the callback is asynchronous by nature.
Can I check if there is a way to know if the above callback is Synchronous or Asynchronous?
Unfotunately without checking the source code of the method/function you're calling you cannot know if it's synchronous or asynchronous.
I am guessing it is Synchronous above because it has to wait till the "slow" animation is over before the alert comes up.
Exactly. You can find this from jQuery's documentation for .hide method:
complete
Type: Function()
A function to call once the animation is complete, called once per matched element.
A callback is a function that will get executed once an Asynchronous process is completed. Let's say we have an object person with the following data.
var person = {
id: 1034
name: 'Julio',
age: 23,
moneyInBank: 0
}
We want to get the the moneyInBank for this person but we don't have access to that information in our local environment. We need to get it from a database in another server, this could take a while depending internet connection, optimization, etc.
getMoneyInBank(person.id, callback) is going to go over that process and fetch the information we need. If we were to run the next script without the callback.
getMoneyInBank(person.id);
console.log(person.money);
We will get 0 in the output because getMoneyInBank has not finished by the time the log is executed. If we want to make sure we will print meaningful information we need to change our code to something like this.
getMoneyInBank(persion.id, function(){
console.log(person.money);
});
Using a callback the log only is going to be called when getMoneyInBank finishes.
You can easily check:
function isSync(func, ...args){
var isSync = false;
const res = func(...args, r => isSync = true);
if(res instanceof Promise) res.then(r => isSync = true);
return isSync;
}
console.log( isSync([].map.bind([])) );
Short answer:
You need to examine the caller and look for async operations.
Long answer:
A callback is a simple pattern by which a function is passed as a parameter to an higher order function and is called back it or further down the stack.
let mySynchronousFunction = () => 'Hello';
let myHigherOrderFunction = aFunc => {
return (aFunc() || 'Goodbye') + ' world!';
};
As soon as there is an I/O operation that would block the main thread, it instead will "branch out" and continue execution.
If we continue with our previous example, we would observe the following behavior:
let myAsyncFunction = () => {
return http.get('http://some.document')
.then(response => console.log(response)
);
};
myHigherOrderFunction(mySynchronousFunction); // 'Hello world!'
myHigherOrderFunction(myAsyncFunction); // 'Goodbye world!'
What happened here is that the main thread continued all the way until it had to wait for I/O and instead of blocking there, it went to the next instruction and took note of the point at which it needs to go when the I/O operation is no longer blocked.
So the next expression to evaluation in our code is:
return expression
But our expression branched out, as such it returns undefined. So we are left with:
return undefined
This means that our higher order function that was passed an async function got undefined when it called aFunc().
Once the I/O is done, the main thread returns to where it left off which is the function passed to Promise handler then. At this point the execution thread has branched out and is separated from main "thread".
Now for your question
The callback will be synchronous when the higher order function which calls it is calling it synchronously. Inversely if it is called within the context of the execution branch of an asynchronous operation it will be asynchronous.
This mean that you need to examine what the higher order function to which you pass your callback is doing and look for async operations.
In the context of your question let us examine the following code (HOF = Higher order function):
let mySynchronousHOC = aFunc => aFunc('Hello world!');
let myAsyncHOC = aFunc => {
http.get('http://hello.com')
.then(response => aFunc('Goodbye world!')
);
};
myAsyncHOC(msg => {
console.log(msg);
});
mySynchronousHOC(msg => {
console.log(msg);
});
The result of which will be:
'Hello world'
'Goodbye world'
Here we know that myAsyncHOC is asynchronous because it does an I/O operation.
I am not sure "synchronous" and "asynchronous" makes sense in this context. You can talk about sync or async when making ajax requests, which would mean that in a sync request everything else stops until the response is received, while in an asynchronous request something else can happen until the server sends the response.
In your particular case ( https://www.w3schools.com/jquery/jquery_callback.asp ) what happens is this:
in the "slow" case a timeout is set and the callback is called when the time is out
in the second case a timeout is set for hiding the paragraph but the function is called imediately on the next line, before the time is out
this is not sync/async, it is about event programming

shall I use callback pattern in my custom function? node js

for example I have a function A that has to return some value
function A(callback){
//some computation
var fakeData = 20;
callback(null,fakeData)
}
function B(err,data){
if(!err){
console.log(data);
}
}
A(B);
so as far as I know only I/O operations in node js runs asynchronously, so whats the difference if I right just this
function A(){
var fakeData = 20;
return fakeData;
}
function B(data){
console.log(data);
}
var data = A();
B(data);
I mean both of them will run synchronously right?
The callback pattern is useful for a number of types of problems:
When your function uses asynchronous operations and you want to be able to notify the caller when the asynchronous operations are complete and perhaps pass a final result to the caller.
When your function wants the caller to supply some function that can be used in the computation of a result as in the callback that can be passed to array.sort(callback).
You would generally NOT use a callback pattern to communicate the result of a synchronous operation because that just makes the code more complicated than just directly returning the result from the function. So, if all your operations in A() are synchronous, then your second code option will be simpler to code and use.
If you are talking about these two functions then yes these two are identical
but this is not the use of callbacks as callbacks are used when you have a process which returns the result after some time or in the future like a database call or a rest api call or a file read/write operations for which we are not sure about when did they returns the result.

Asynchronous call to synchronous function

Lets say I have an synchronous function for example:
var sum = function(x,y){
return x+y
}
I want to call this function in asynchronously. How is that possible? Is the function below be considered an asynchronous function? If this is an asynchronous function then I second function's log should be logged before the first one? I know this is a very simple example which may not be an ideal case for async function. But I just wanted to get this fundamental clear.
function(a, b, c, d, e, f, function(){
console.log(result);
})
{
result = sum(a, b);
result = sum(result, c);
result = sum(result, d);
result = sum(result, e);
result = sum(result, f);
return
)};
function(a, b, function(){
console.log(result);
})
{
result = sum(a, b);
return
)};
Please help me. If this is not correct then please help me in as to How it should be written?
From your comment on Quentin's answer
How to create a function which has some manipulation inside it which is a normal synchronous function but the overall flow doesn't wait for this function to complete rather moves to the next function.
JavaScript, the language, doesn't have a feature to do that. So you look to the environment in which it's running to see if the environment has that feature.
NodeJS does. In fact, it has several of them: setTimeout (which is a bit like what browsers give you), setImmediate, and process.nextTick. For your use case, setImmediate is probably the best choice, but see this question and its answers for more on that. setImmediate looks like this:
setImmediate(functionToCall);
(It's a global, you don't have to require anything.)
That does exactly what your title asks for: An asynchronous call to a synchronous function.
From your comment below:
I just need to create an async function inside which I call a normal synchronous function. When I mean asynchronous function I mean that when I call this function it doesn't obstruct the flow and the flow goes to the next function and this function can do something(like logging) after completion
That's not quite the same thing your question asks. :-)
First off, there are no asynchronous functions (in JavaScript). When you call a function in JavaScript, that function is executed synchronously. So that means you have two choices:
The calling code can use setImmediate to tell Node to call the function asynchronously, or
The function can do that for itself, probably using a nested function.
Here's #1:
function foo() {
console.log("A");
setImmediate(bar);
console.log("B");
}
function bar() {
console.log("C");
}
foo();
which outputs:
A
B
C
Here's #2:
function foo() {
console.log("A");
bar("C");
console.log("B");
}
function bar(arg) {
setImmediate(run);
function run() {
console.log(arg);
}
}
foo();
...which also outputs
A
B
C
Note how "C" was passed as an argument to bar. bar does nothing but schedule the callback to its nested function run. run uses the argument.
How is that possible?
It isn't. Everything it does is a synchronous operation.
You use asynchronous code when dealing with things which are intrinsically asynchronous. This is limited, in JS, almost entirely to event handling.
Is the function below be considered an asynchronous function?
No. It has a callback, but everything it does is synchronous.
I'm not completely sure that I understand what you need, but I believe that what you're looking for is to create concurrent function calls, which means you probably need to run a potentially computationally intensive code, and you don't want it to block other code from executing while this computation runs.
Node.js is usually used in a single-threaded process, which means that only a single piece of code can run at a given time, but there are still some ways to do it.
One way to do it, as stated in #T.J. Crowder 's answer, is to queue your function call with process.nextTick so it'll run on the next cycle of the event-loop. This can help break down intensive computation into iterations and that each iteration will be queued to run on the next event-loop cycle after the last one. This can help in some cases, but not always you can break down computations into iterations that run async from each other. If you're looking for a more detailed explanation into how Javascript runs asynchronously, I suggest reading this book.
There are at least two other ways (that I know of) to achieve some sort of concurrency with Node.js- Workers/Threads, and child processes.
Child processes in short are just another Node.js process that is run by your main application. You can use the native *child_process* module of Node.js to run and manage your child processes if you want to go this way. Look at the official docs for more info.
The third way to do it is to use Workers in a very similar manner to how Web Workers are used in the browser. A Worker is a snippet of code that is run in a different OS thread than your main application. To me it seems that this is the easiest way to achieve concurrency, although some will argue it is not the most robust way of doing it, and that creating child processes is better.
There a very good explanation of how Workers function on MDN. To use Workers in Node.js you will need an external module such as webworker-threads.
Here's a code sample created from your sample with a snippet from their documentation:
var Worker = require('webworker-threads').Worker;
var worker = new Worker(function(){
onmessage = function(event) {
result = sum(event.data.a, event.data.b);
result = sum(result, event.data.c);
result = sum(result, event.data.d);
result = sum(result, event.data.e);
result = sum(result, event.data.f);
postMessage(result);
self.close();
};
});
worker.onmessage = function(event) {
console.log("The result is: " + event.data);
};
worker.postMessage({a: 1, b: 2, c: 3, d: 4, e: 5, f: 6});
// Do some other stuff that will happen while your Worker runs...
With all that said, most people will try to avoid running concurrent code in Node.js. Javascript's async nature makes it easy to write simple and concise back-end code, and usually you would want to keep it that way by not trying to introduce concurrency into your application, unless it is absolutely necessary.
In Javascript (leaving node aside for a moment) An asynchronous function should be called via setTimeout(). SetTimeout will not block the script execution while waiting:
function someThingThatTakesAWhile() {
for (var i = 0; i < someVeryLargeNumber; i++) {
//...
};
}
setTimeout(function () {
someThingThatTakesAWhile();
}, 0);
(haven't tested that, please forgive typos, &c)
But if you're wanting to do this in node, I don't think this is what you really want.

Is "if ( somefunction( ) )" blocking in node.js?

test = function(x){
if ( some conditions ) { return true; }
else { return false; }
}
if (test(y)) {document.write("You have done this before!")​}​;​
console.log("Checked!");
The intention is to check if the user performed some action in the past. These are just mock up codes that do not really reflect what I am actually doing though.
Question:
I am relatively new to node.js so please forgive me if this sounds trivial. Suppose test(y) is true. Can I be sure that the console.log will be executed after the document.write? Even if test(y) takes a long time to run?
In other words, I need "if (test(y))..." to be blocking. I understand that passing a function as an argument, e.g. setInterval(test(y),100); can be async and non-blocking. But what about "if(test(y))..."?
NodeJS has both synchronous (blocking) and asynchronous (non-blocking) functions. (More accurately: The functions themselves are always "blocking" but a whole class of them start something that will complete later and then return immediately, not waiting for the thing to finish. Those are what I mean by "non-blocking.")
The default in most cases is asynchronous (and they accept a callback they call when the thing they've started is done); the synchronous ones tend to have names ending in Sync.
So for example, exists is asynchronous (non-blocking), it doesn't have a return value and instead calls a callback when it's done. existsSync is synchronous (blocking); it returns its result rather than having a callback.
If test is your own function, and it only calls synchronous functions, then it's synchronous:
function test(x) { // Obviously a nonsense example, as it just replicates `existsSync`
if (existsSync(x)) {
// The file exists
return true;
}
return false;
}
// This works
if (test("foo.txt")) {
// ...
}
If it calls an asynchronous function, it's asynchronous, and so it can't return a result via a return value that can be tested by if:
// WRONG, always returns `undefined`
function test(x) {
var retVal;
exists(x, function(flag) {
retVal = flag;
});
return retVal;
}
Instead, you have to provide a callback:
function test(x, callback) {
exists(x, function(flag) {
callback(flag);
});
}
// This works
test("foo.txt", function(flag) {
if (flag) {
// ...
}
});
Yes, this code is synchronous executed and "blocking". But console.log will be executed every time the script runs because you only omitting the document.write in the if statement.
The blocking/non-blocking terminology is a bit confusing here, I would say 'all functions in Node.JS are blocking and all IO in node standard library is non-blocking, except when indicated explicitly by Sync suffix in function name'.

Categories