I am new to nodejs, recently I am not sure how to arrange tasks in order such that they behave correctly.
below are two examples
arr.forEach(function(elem){
//do many many things
});
console.log('done, now take ur pick');
stdin.on('input', function action(){
...
})
how can I set stdin.on fire after arr.forEach.
and question 2 I think if I do
fn1();
fn2();
function fn1(){
//long long code
}
function fn2(){
console.log('fn2 is done!')
}
and runs the above, the execution will be in a thread of
fn1 fn2 fn1 fn1 fn1, right? how to prevent this?
Functions in node.js are either synchronous or asynchronous. Synchronous code runs in a single thread, and behaves exactly like the code you're used to:
fn1();
fn2();
fn3(fn4());
Will run fn1, then fn2, then fn4, then fn3 (passing in the result of fn4 as a parameter).
Asynchronous code fires off some action, and takes as a parameter the function to execute when it's done (which might, in turn, fire off another asynchronous action). You get control back immediately. Example:
doSomeAsyncThing(function () {
console.log("did the async thing");
});
console.log("hello");
executes like this: First, the asynchronous action is fired off, then "hello" is printed. Some time later, the asynchronous action completes, so the callback is called, and "did the async thing" is printed.
If you want to do one asynchronous thing, then do another asynchronous thing after the first one is finished, the standard way to is nest the callbacks:
async1(function() {
async2(function() {
console.log("async1 and async2 finished");
});
});
Although there are better options.
So in your second example, if fn1 is synchronous, it will work perfectly exactly as you wrote it. If fn1 has to do something asynchronous, it too will have to be asynchronous, so you will have to write it like this:
function fn1(callback) {
// do some sync stuff
doSomethingAsync(function () {
// do more sync stuff
doSomethingMoreAsync(function () {
// do more sync stuff
callback(); // call the callback once everything is completed
});
});
}
And then call it like this
fn1(function () {
fn2();
});
Which could be simplified to:
fn1(fn2);
In your first example, note that array.forEach is synchronous. If your // do many many things are all synchronous, then that will work exactly as you wrote it, but if there's an asynchronous action in there, you can either manually implement a counter, or just use the async library or Promise iterator utilities.
by adding the stdin to the callback function of the forEach function. Like:
arr.forEach(function(elem){
//do many many things
}, function() {
console.log('done, now take ur pick');
stdin.on('input', function action(){
...
});
});
Using this, the stdin and console.log functions will be called only after completion of the forEach loop.
Related
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.
The situation is as follows:
A button is pushed by the user which fires an event handler consisting of 4 functions. One of these functions does some async job and then enters a cascade of synchronous and (depending on the usecase) asynchronous functions. The code looks roughly like this:
$('#someButton').Click(function(){
handler();
})
async function handler(){
syncFunction1();
syncFunction2();
await asyncFunction3();
syncFunction4();
}
function asyncFunction3(){
$.post('someUrl',{
//nothing to transmit
}).then((jsonString) => {
parseJSONtoObject(jsonString)
})
}
function parseJSONtoObject(data){
//some Code for Conversion
callCascadeOfFunctions();
}
function callCascadeOfFunctions(){
//some Code which calls other functions
//which call other functions
//and so on
//here is some illustration of what "callCascadeOfFunctions()" does:
//some code
cascadeStep1();
}
function cascadeStep1(){
if(X){
cascadeStep2A
}else{
cascadeStep2B
}
}
//this continues, sometimes the cascade splits, sometimes not.
//at some point we have another AJAX, coming in like this
function cascadeStepN(){
//some code
await sideCascadeWithAJAX
//some code, leading deeper into the cascade where only synchronous
//operations happen
}
}
Now, what's very important is that handler() waits for the asyncFunction3() cascade to finish before it continues.
In another case, I already returned a promise from the depths of a cascade of functions. However, this code looked more like this:
function foo(){
//some code
await someFunctionCascade();
//call to other functions
}
function someFunctionCascade(){
//call to another synchronous function which calls another function etc..
//at the end of the cascade a function does jquery AJAX which creates a promise
//which is returned all the way up through the cascade to the original call
//inside foo()
}
But this time its a bit more tricky, because the cascade contains both synchronous and asynchronous parts. It starts with the AJAX, enters a cascade of synchronous functions which at some point call an asynchronous function and wait for it to finish, and THEN continues through some synchronous functions to its end.
Do I really need to chain all of this into "thens" or can I circumvent this by returning the promises from the asynchronous all the way up to the original call?
And if so, would this "combination" of a then-structure with the passing up of promises through the synchronous sections work, or is it impossible this way?
cascadeStep1 needs to return the result from cascadeStep2A and cascadeStep2B. Since all of these are async functions they will return a promise.
callCascadeOfFunctions needs to return the result of casecadeStep1.
Basically, once you work with async functions or functions that do 'things' with promises, they need to all return a promise. As long as everything returns a promise that resolves when their inner operation is complete, await can behave correctly.
synchronous functions which at some point call an asynchronous function and wait for it to finish
By that moment, the "synchronous function" is no longer synchronous. It's asynchronous and should return a promise (for a result value or for undefined). It can do that either by returning the promise that the asynchronous call returns, by using then on that promise if it wants to do something else after the async call, or by awaiting the promise.
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
In my code, I want to test if a function is asynchronous, and if it is, use it's callback function. But if not, then I'll just call the next function manually. So is there a way to test if a function is asynchronous? And if not, then where could I find a list of all asynchronous jQuery functions?
if (isAsynchronous(fn)) {
args.push(function () { alert('callback!'); });
this.fn.apply(this, args);
} else {
this.fn.apply(this, args);
alert('synchronous');
}
So if that is not possible, having a list would be the next best thing.
var asynchs = {
animate: true,
fadeIn: true
//etc...
};
if (asynchs[fn]) {
args.push(function () {alert('callback!'); });
this.fn.apply(this, args);
} else {
this.fn.apply(this, args);
alert('synchronous');
}
There is no programmatic way to determine if a function is synchronous or asynchronous. In fact, it's possible for a function to be either synchronous or asynchronous depending upon what it's passed. Like $.ajax() can be passed a parameter that determines which it is.
So, if you want to know what a function is, you have to either read the doc or the code.
In general, if a function offers a "completion" callback or something like that, then you should suspect that it's probably asynchronous or has an asynchronous option and look in the documentation to confirm. If a jQuery method does not have a completion callback, then it's probably not asynchronous.
Other things like $.each() just use callbacks as part of their implementation (they are not "completion" callbacks) and are not asynchronous.
You should also suspect that ANY method that does animation or networking or waits some period of time is probably asynchronous. The jquery doc is really well written so it's usually pretty trivial to take a quick look if you're unsure.
I have recently started with node.js. It quotes that node.js asynchronous behaviour can be used in three ways events, stream, callback.
Events and stream work on emit,pipe event making it truly async, but how is callback async, as it executes before the return of the function unless process.nextTick() is used.
Events:
event.on('data',function(data){
});
Callback:
function(data,cb){
// do something with "data"
cb();
return;
}
Let's take a closer look at your function that has a callback:
function(data, cb) {
// do something with "data"
cb();
return;
}
You have 2 big errors here:
1) You have no reason to use return when you have a callback function. Return is used only when you have synchronous actions that send a response back right away (they do not have to wait for a callback to be triggered sometime in the future).
2) You don't execute the callback immediately, it doesn't make any sense. You either don't use a callback and use a return statement (when you don't really have an async function) or you execute the callback sometime in the future, when you get the result.
Better example:
function (data, cb) {
// you make an Ajax call and
// you don't know when the callback will be triggered
makeAjaxCall(data, cb);
}
You're correct in that callbacks don't necessarily mean asynchronous I/O.
Events aren't necessarily asynchronous either, in the sense that EventEmitter's .emit works immediately, not on the next tick:
var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter();
emitter.on('ev', function(x) {
console.log("received event ", x);
});
console.log("Hello");
emitter.emit('ev', "X");
console.log("World");
Result:
Hello
received event X
World
However, callbacks can be made "async" by:
using process.nextTick(). This doesn't make the actual I/O operations inside the callback async. It just defers execution until the next tick. If some operation blocks, the event loop will also block - on the next tick instead of this tick.
function(data, cb) {
process.nextTick(function() { doSomethingWith(data); cb(); })
});
calling the specified callback function from an event that is known to be triggered by an async I/O operation
function(data, cb) {
emitter.startIO();
emitter.on('someIOEvent', function(e) {
doSomethingWith(data,e);
cb();
});
});
using another callback-based function known to be async. Most functions in node core and node's modules are like this.
function(data, cb) {
otherFunction(data, function(moredata) {
doMoreStuffWith(moredata, data); cb();
});
});
In this case, the function with the callback is not being run asynchronously, however there are still cases where such functions can be used asynchronously:
function foo(data, callback) {
// do something with the data
callback();
}
function bar() {
// this will be called as a callback from foo()
}
setInterval(function() { foo(data, bar) }, 1000);
console.log('this is displayed immediately');
You can see that foo() is scheduled to run every second, and that happens asynchronously; however the existence of the callback allows you to set up extra behavior from outside the foo() function, e.g. you might set up several cases where foo() is called with different callbacks, resulting in different application logic.