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.