Async Function Call in Recursion using node js - javascript

How to call Async function in recursion actually I have Async method - async function getSSN(req,res,next) and inside this function block I need to call this function but when I call this method by code - return await getSSN(req,res,next) this code is not working for me in node js. Can anyone give me solution for that.?

So, you can't mix async/await with plain asynchronous callbacks. They do not work properly. Your async function getSSN() is not properly resolving when your request.get() finishes because that's just a plain asynchronous callback which the async function knows nothing about.
Instead, you need to use a promise-based request() option. Since, the request library is now deprecated and should not be used for new projects, I would suggest one of the alternatives that are all based on promises already. My favorite is the got() library, but you can look at the list of alternatives and pick the one that has a programming style you like.
In addition, your getSSN() function has a bunch of side effects (modifying higher scoped variables). This is not a good way to program, particularly for asynchronous operations because the outside world generally doesn't know when things are done and when the higher scoped variables have the values in them you want them to. You should make getSSN() return a promise that resolves to its result and then have the caller use that result to modify the higher scoped variables. Again, if you showed us the rest of the coding context here, we could suggest a better overall way to do this. Please notice here that you're just not providing enough code for us to be able to show you the best way to write this code. That should be a general lesson for stackoverflow. Err on the side of giving us more than you think and we can then often make suggestions and improvements far beyond what you even know to ask about.
Here's your function with all the ill-adivsed side effects still in it (because you haven't shown us the rest of the code) using got():
async function getSSN(next) {
const result = await got('idms.dealersocket.com/api/account/…').json();
if (count <= totalpage) {
const data = Object.assign({}, result.Data);
const len = Object.keys(data).length;
for (var i = 0; i <= len; i++) {
ssn.push(data[i].Row.Borrower1SSN);
}
count++;
}
}
Now, getSSN() will return a promise that resolves or rejects when the network request is finished.

Related

Why doesn't .then() need the async keyword when used (similar to await)? How does Javascript know it's an asynchronous operation?

I'm starting to learn asynchronous Javascript and I'm really confused.
To be honest, the async/await approach seems very logical to me. We need to let the runtime know we're doing an asynchronous operation so it can handle it accordingly. But why don't we need to do the same when using the .then() method? I mean, if Javascript was already able to understand when promises are handled, couldn't await just be used without async just like .then()?
To make it even more confusing, I saw people using .then() directly inside functions declared with the async keyword. Wasn't async/await supposed to be syntactic sugar for the .then().catch() approach? Why can these be combined, especially inside one another? Using .then() on the result of the async function wouldn't have been as confusing, but being inside one another makes me have even a harder time understanding this.
I really searched everywhere for an explanation on this and couldn't find an answer for this exact question. All I've found was people saying you can use both approaches because they essentially are the same thing, but when you get in the details, things aren't very clear.
So the async function always returns a promise. Inside it, await always handles promises. .then() can be chained to the await function. .then() can also be chained to the result of the async function. Same with the .catch method if we don't want to use try/catch on the await. Why is it so mixed up? Can we handle the return of async without .then()? If async/await really is syntactic sugar for .then(), why doesn't .then() also always return a promise after it resolves?
If anybody can help with some clarification, I would truly appreciate it. Thank you!
There's so many questions here, but one way to think about it is... Promises are not asynchronous operations, they are just a standard pattern that helps users deal with existing asynchronous operations in a predicable way.
There's nothing special about .then(). It's not a Javascript keyword, and javascript doesn't need to be 'aware' of then in any way.
Promises are a pattern. You can write a promise class yourself from scratch (I'd highly recommend this). When you use .then(), and you pass it a function, you are telling the promise class: "When the promise resolves, please call this function for me".
All of this existed before async/await. Async/await was added after to make it easier to work with promises.
I find the question if 'something is syntactic sugar' meaningless. It suggests that a language feature is not that meaningful because the same thing could be accomplished before the language feature existed. While this might be true, this is true for any programming language when compared to, say, assembly. To me the definition of 'syntax sugar' can be extended to almost anything, so it's not a useful designation.
What async/await (and generators before it) adds to the language, is that a javascript function can be interrupted and resumed later after some condition.
Lastly, .then() and .catch() always return promises. If you see a .then() function that doesn't, then it's not compatible with the Promise/A+ spec.
If you are willing to put in the work to fully understand this, I would recommend the following 2 exercises:
Write your own Promise class
Re-implement async/await using generator functions (see the co package of how this was done before async/await landed)
The purpose of async/await is to allow writing async code in a serial manner, which is mentally simpler to reason about (for some human-beings). This is useful, if you need to wait for async operation to finish before you continue with the rest of the code. For example, if you need to pass result of async operation as parameter.
Example 1
function asyncOperation1(n) { return Promise.resolve(n+1); }
function asyncOperation2(n) { return Promise.resolve(n/2); }
function asyncOperation3(n) { return Promise.resolve(n*3); }
function errorHandler(err) { console.error(err); }
function main() {
// flow-control
asyncOperation1(1)
.then(asyncOperation2)
.then(asyncOperation3)
.then(continueAfterAsync)
.catch(errorHandler)
// function wrapper
function continueAfterAsync(result) {
console.log(result);
}
}
main();
With async/await the code of the main function above may look like
async main() {
try {
console.log(
await asyncOperation3(
await asyncOperation2(
await asyncOperation1(1)
)
)
);
} catch(err) {
errorHandler(err);
}
}
Pay attention that we don't need to rewrite async operation functions to be async function asyncOperation... to use await, but we need to declare main function as async main.
Which one is better(?) is the mater of developers's taste and previous programming languages experience. The benefit that I can see is that you don't need to wrap everything into functions and introduce additional flow-control code, leaving this complexity to JavaScript compiler.
However, there are cases, when you want to schedule some parallel tasks and you don't care which one will finish first. These kind of things would be relatively hard to do with async/await only.
Example 2
function main() {
Promise
.all(
['srv1', 'srv2', 'srv3'].map(
srv => fetch(`${srv}.test.com/status`)
)
])
.then(
responses => responses.some(res => res.status !== 200) ?
console.error('some servers have problems') :
console.log('everything is fine')
)
.catch(err => console.error('some servers are not reachable', err))
}
So, we see that there is a room for both .then() and await to coexist.
In some cases function may be either synchronous or asynchronous, depending on business logic (I know it's ugly, but in some cases it's unavoidable). And here we come to your main question
why don't we need to mark an asynchronous operation with .then() and we have to do it with await
In other words, why do we need async keyword at all?
Example 3
// without `async`
function checkStatus(srv) {
if (!srv.startsWith('srv')) {
throw new Error('An argument passed to checkStatus should start with "srv"')
}
return fetch(`https://${srv}.test.com/status`);
}
function main() {
// this code will print message
checkStatus('srv1')
.then(res => console.log(`Status is ${res.status === 200 ? 'ok': 'error'}`))
.catch(err => console.error(err));
// this code will fail with
// Uncaught TypeError: (intermediate value).then is not a function
checkStatus('svr1')
.then(res => console.log(`Status is ${res.status === 200 ? 'ok': 'error'}`))
.catch(err => console.error(err));
}
However, if we define async function checkStatus, compiler will wrap the runtime error into rejected promise return value, and both parts of the main function will work.
Now let's imagine that JavaScript allows to write functions that use await without specifying async in front of them.
Example 4 (not a valid Javascript)
function checkStatus(srv) {
if (cache[srv]) {
data = cache[srv];
} else {
data = (await fetch(`https://${srv}.test.com/status`)).json();
}
data.x.y = 'y';
return data;
}
What would you expect checkStatus to return? Promise, raw value or throw exception (in case data.x is undefined)?
If you say Promise, then it would be hard for developer that uses this function to understand why inside of checkStatus one can write data.x and outside of it (await data).x is required.
If raw value, the whole execution flow becomes cumbersome, and you can no longer rely on the fact that JavaScript is a single-threaded language, where no-one can change the value of the variable between two lines of code that are written in serial manner.
As you noticed, async/await is a syntactic sugar. If this syntax allows me to avoid possible runtime errors at earlier stage and keep the language backward compatible, I'm eager to pay the price of putting extra async in front of async functions.
Also, I would recommend to read the answers to JS async/await - why does await need async?
In a simple explanation, async/await is syntactic sugar (the node interpreter/compiler/optimizer will convert everything to normal Promises).
The goal of this feature is turn our life easy, because the callback way/style of programming eventually lead us to make mistakes. We call this "the callback hell"
So, we can use .then() when calling functions that is decorated with async keyword, and we can await on functions that return Promise objects.
It's important for optimizations in general, that the code we write tells the compiler what we are meaning, in terms of performance. Imagine if all our codes / lines of code / instructions could be async or sync at the same time. This would lead the computers perform bad, because the task of check this during runtime is very expensive.
So that's why it's so important to us code instructions in an efficient manner.

Why should we wrap await inside an async function?

Why should we have an async function in order to use await? Why can't we just use await without async? JS is async by default too, this just adds to the confusion.
Update:
I've seen some lads put my question on hold so I'll try to elaborate.
I'm just curious as to why this won't work:
some code
let users = await getUsers();
some code
Why should it be inside an async for it to work, ie
$(async function() {
some code
let users = await getUsers();
some code
});
JS is async by default too...
No, JavaScript is not async by default. The only async features of JavaScript are fairly newly-added:
Promise resolution
async/await
JavaScript is commonly used in environments where you interact with asynchronous things (like event handlers in the DOM, or I/O completions in Node.js), but JavaScript is not asynchronous (other than above).
In the words of Allen Wirfs-Brock, who was the editor of the ECMAScript specification for many years, JavaScript...
(has) an observably synchronous execution model. Other than via Atomics/SABs there are no observable shared-state race conditions.
Back to your question:
Why should we have an async function in order to use await?
Before too long, with modules you won't have to, once the top level await proposal finishes working through the process. It just got to Stage 3.
But the answer is that await is syntactic sugar for consuming a promise, and one of the rules of promises is that you either handle errors or return the chain to the caller (so it can handle errors or return the chain to its caller). await doesn't handle errors, so it has to return the chain to the caller. The way it does that is that an async function always returns a promise, and that promise is chained to the promise await awaits.
That is, this:
async function foo() {
const thingy = await somethingAsyncReturningAPromise();
return thingy.foo;
}
is conceptually (but not literally) this:
function foo() {
return somethingAsyncReturningAPromise()
.then(thingy => thingy.foo);
}
If something goes wrong in somethingAsyncReturningAPromise, the promise returned by foo rejects — the error is propagated to the caller.
As far as I can tell from the top-level await proposal, it simply allows unhandled rejections at the top level of the module to be unhandled rejections. So just like this code causes an unhandled error:
null.doSomething();
this code in an async module would cause an unhandled rejection:
await somethingThatReturnsAPromiseAndRejects();
Why should we have an async function in order to use await? Why can't we just use await without async?
Because async/await is "just" syntactic sugar for Promises. If the function is async, then it returns a Promise. It is not possible to have the "await" behaviour without returning a promise. The fact that the function is async has to be marked explicitly.
JS is async by default too, this just adds to the confusion.
This statement is too "simplified". While it is true that JS is async in nature, because of the event loop, this doesn't mean that every function has an async behavior. This does not add to the confusion. You're probably confused due to misunderstanding how JS really works. You should read about Promises, which are behind the scenes when you see async/await.
JavaScript has task based concurrency. It basically means that code blocks (tasks) runs synchronously without being interrupted, until it reaches a certain breakpoint (the end of a task). That has some advantages:
1) You do have concurrency, e.g. a network call does not block your script from doing other things in the meantime (so the task that consumes the network request will only run if the network request was done, other tasks can be done in the meantime).
2) On the other hand, you do not have concurrent mutations, which eliminates a lot of problems (let a = 1; a += 1; could evaluate to 3, you would need locks / semaphores to prevent those, c.f. Java & others).
Now async / await allow you to define such tasks:
An async function can be divided into tasks, await serves as a breakpoint:
let a = 1;
async function stuff() {
a = a + 1; // this is totally secure, as no other code might run in the meantime
a = a + await other(); // this is unsafe, as we await, which means that other tasks might be executed in the meantime.
}
If you want to "await in non async functions" that basically means that you won't know wether a certain function call runs synchronously (meaning: without other code running in the meantime) or not:
function dangerous() { await stuff(); }
let a = 1;
a = a + dangerous(); // does that work or not? Can a be manipulated in the meantime?
So with your proposal you would basically remove the borders around tasks, every code might run every inbetween. So at the end that causes chaos, and chaos is not good if you want to be productive.

Javascript promises deep in the stack

I decided to have a fallback call to the server when creating a model in case we can't find a value from the information available locally. I want to have it async if possible, does it mean I have to make everything in this chain of code consume and return promises?
I'm going to use pseudo code to illustrate this point initially, as the call stack can be a little long and so we don't include things that aren't central to this question. Let me know if you need more to go on though.
function router() {
if (condition) {
controller.renderDocument(options);
}
}
controller.renderDocument(options) {
documentCollection.findOrCreateDocumentHolder(options);
}
documentCollection.findOrCreateDocumentHolder(options) {
var model = this.findOrCreateDocument(options);
}
documentCollection.otherFunction(options) {
// just to illustrate that there's several entry points to this kind of functionality
var model = this.findOrCreateDocument(options);
}
documentCollection.findOrCreateDocument(options) {
if (!options.type)
options.type = resolveType(options);
// other things that use the found options.type
return model;
}
resolveType(options) {
var locallyResolved = resolveLocally(options);
if (locallyResolved)
return locallyResolved;
// try the server as a fallback
var serverResolved = resolveFromServer(options.id);
return serverResolved;
}
resolveLocally(options) {
return stuff;
}
resolveFromServer(id) {
return ajaxRequestResult();
}
Obviously the actual code is a bit longer and actually does stuff.
It feels excessive to make all of this use chaining promises for the sake of 1 possible ajax request down the pipe, especially as this will be a rare occurrence. The other alternative is to just make a synchronous AJAX request.
Are my only options to make everything use promises and whens, or to make it a synchronous AJAX request? Is there a nicer alternative? I'm thinking of C#'s await keyword, but I'm sure other languages have similar functionality.
I want to have it async if possible, does it mean I have to make everything in this chain of code consume and return promises?
Yes. Something that is potentially asynchronous must always return a promise, and must always be consumed as if it was asynchronous (promises enforce this anyway).
Is the only other alternative to just make a synchronous AJAX request?
Yes, and you really don't want that.
Is there a nicer alternative? I'm thinking of C#'s await keyword, but I'm sure other languages have similar functionality.
In fact, async-await is coming to ECMAScript as well. But it doesn't make anything synchronous, it rather is just syntactic sugar for promises-everywhere.
Once you start with promises they do spread around, no way around it really since once you go async you must either wait (not feasible) or pass callbacks (which promises solve).
My approach is to embrace them, you'll be more often returning promises then immediate values, but you'll always take care of handling success/error and have a consistent way of dealing with data flow.
There are many more sources of asynchronicity than AJAX requests and I really can't think of a case where I would require a synchronous return value in Javascript.

Asserting values in node.js

I have a function,
Edit1 - Updated function with real one because the previous one was simplified synchronous function and the code would have worked as correctly pointed by #AlexMA in the comments
'returnSuccessOrFailure': function () {
return driver.findElement(wd.By.css('div#button')).then(function (button) {
return button.getAttribute('class').then(function (status) {
return status;
});
});
}
In my node.js test, my assertion is failing because the assert is called before returnSuccessOrFailure finishes execution.
var value = returnSuccessOrFailure();
assert.equal(value,'success', 'Looks like something failed');
If I implement a promise in returnSuccessOrFailure and chain my assert then that works. My question is do I have to implement promises all the time for such situations to block the execution? I am new to Javascript and the async nature of it and any insight when to use promises and when not to would be useful.
you don't have to "implement a promise" in, just return the one you already have:
returnSuccessOrFailure': function () {
return driver.findElement(wd.By.css('div#button')).then(function (button) {
...
but then, yes, you do still need to put your assert in a done handler
returnSuccessOrFailure().done(function(value) {
assert.equal(value,'success', 'Looks like something failed');
}
Chaining you asserts will not only make it work but will also make for more readable code. Knowing what happens in what order can be useful when going back to refactor. Not only that but the structure of callbacks/promises also allow for easily written timer tests.
Also, since your test needs to have the current state of execution, it is more than likely that writing tests with asserts in callbacks is what you will need anyway.
My question is do I have to implement promises all the time for such situations to block the execution?
Notice that promises don't block the execution. They defer the execution of code that depends on the result, notice that you're still chaining callbacks on them.
I am new to Javascript and the async nature of it and any insight when to use promises and when not to would be useful.
Promises are useful wherever you have some code that might run asynchronously and needs to pass back an asynchronous result. Otherwise you would need to use callbacks, which are way more ugly than promises.
This is part of code contracts and representing preconditions (what holds before you execute), postconditions (what holds after you execute), and object invariants (what can not change). JavaScript does not have native support for this, but you can use third party libraries (Cerny.js, ecmaDebug, jsContract, or jscategory)
I think it depends on your coding style, is it EAFP(Easier to ask for forgiveness than permission) or LBYL(Look before you leap). Both are viable! In most compiled languages you would use LBYL. However in Python for example you would use EAFP.
Generally if you know you will fail you want to fail fast. If you like to use assertions to ensure code fails fast it is up to you.

Need Help Thinking How to Program Asynchronously

I'm using NodeJS to walk over a list of files and generate an MD5 hash for each one. Here's how I would normally do this synchronously:
// Assume files is already populated with an array of file objects
for(file in files) {
var currentFile = files[file];
currentFile.md5 = md5(file.path);
}
The problem here is that the MD5 function is asynchronous and actually has a callback function that is runs once the MD5 hash has been generated for the file. Thus, all of my currentFile.md5 variables are just going to be set to undefined.
Once I have gotten all of the MD5 hashes for all of the files I'll need to move onto another function to deal with that information.
How gnarly is the code going to get in order for me to do this asynchronously? What's the cleanest way to accomplish what I want to do? Are there common different approaches that I should be aware of?
To call an async function multiple times, you should make a function and call it in recursion like this.
I have assumed your md5 function has a callback with two params err and result.
var keys = Object.keys(files); // taking all keys in an array.
function fn() {
var currentFile = files[keys.shift()];
md5(currentFile, function (err, result) {
// Use result, store somewhere
// check if more files
if (keys.length) {
fn();
} else {
// done
}
});
}
One great approach is to use async. (Search on npm)
If you want to roll your own
Count the files, put that in a var
Everytime fs opens a file and calls your intermediate callback, compute and store the MD5
Also, decrement that counter.
When counter === 0, call a "final" callback, passing back all the MD5s.
To answer your questions (theoretically), in Javascript world, there are (at the moment) 2 different ways to deal with asynchronous code
Using callbacks. This is the most basic way that people start using Javascript know. However , there are plenty of libraries to help people deal with callback in a less painful way such as async, step. In your particular problem. Assuming that md5 is somehow weirdly asynchronous, you can use https://github.com/caolan/async#parallel to achieve it
Another way is to use promise, there are also plenty of promise-compliant libraries such as q, when. Basically, with a promise you have a nicer way to organize your code flow (IMO). With the problem above you can use when.all to gather the result of md5. However, you need to turn md5 into a promise-compliant function
To avoid "callback hell" you should introduce the world of promises to your Node toolset. I suggest q https://npmjs.org/package/q
Here is a post on SO that can help and give you an idea of the syntax how to use q.js promises to work with multiple asynchronous operations.
You essentially would run all your async functions with defered promises, the .then() chained method would fire when all promises are resolved and the function passed inside then() can process your MD5'd data.
I hope this helps.

Categories