async await try catch performance issue - node.js

I wrote a Javascript code using async, await and used try, catch in each async function.
Suppose if I write 10 async function then I need to write try, catch in all those 10 functions. Now I am getting question in my mind that doesn't it cause performance overhead?
If it causes any performance overhead then what will be the solution for this problem?

You can write single try catch, in try you can add all of the async-await functions.
try {
// service as an example
const get = await service.get()
const post = await service.post()
const delete = await service.delete()
} catch(e) {
throw new Error(e)
}

Related

NodeJS await inside forEach function

I am working with MySQL server, building a NodeJS server.
SomeWhere in the code I have async code that is not waiting, I believe its has something to do with the forEach function.
Is there anything wrong with my implementation of my next function:
async addResponsesToTasks(input, response, isFromCache) {
if (!isFromCache) {
this.saveResponseToCache(input, response);
}
console.log("===7===");
await response.forEach(async (pokemon) => {
console.log("===8===", pokemon);
await this.addTaskToFile(pokemon, false);
console.log("===13===");
});
return true;
}
And this is the output shows that it is not waiting for creation and save in the DB to finish, and jump to do some other things:
Prints of the output - can see 10,12,13,14,15 and only then 11
Hope you could maybe spot what I am missing.
Thanks in advance!
What's happening here is more of a JavaScript thing than a Sequelize thing.
The await is being applied to the lines of code that follow Item.create() inside of this function, but outer functions are continuing to execute.
console.log('9')
saveTaskToDb(task)
console.log('12')
In this code, '12' is going to get logged out before your '11', because this outer code is going to continue to execute, even if the code in saveTaskToDb is awaiting the resolution of the create() method.
To solve this, you'll either need to move all of your asynchronous code into the same code block, or you'll need to return your own promise in the saveTaskToDb function, and await saveTaskToDb.
So Solution was not using forEach, rather using for of loop like that:
async addResponsesToTasks(input, response, isFromCache) {
if (!isFromCache) {
this.saveResponseToCache(input, response);
}
for (const pokemon of response) {
await this.addTaskToFile(pokemon, false);
}
return true;
}
Based on this question: Using async/await with a forEach loop

Compare Async/await vs then [duplicate]

I am looking for a answer on what to use in my nodeJS app.
I have code which handles my generic dB access to mssql. This code is written using an async functions and then I used a promise to call that function and all works fine.
As my app is getting bigger and code larger I am planning to move some of the logic into functions and then call them.
So my question is: is there a drawback to using a mix of async/await and promises or does it really not matter?
Async / await makes it easier to write more readable code as I have to read and write to multiple db’s before I return something and I need results of some of these.
So the question is what is the better approach?
Async / await on dB layer that’s set and can’t change
The logic layer async / await which would allow me a async / and await on the function call or if I go with promise for logic then I am stuck with promise on function call.
So I hope someone can give me more insight if one has more advantages than the other, besides being able to write cleaner code.
async/await and promises are closely related. async functions return promises, and await is syntactic sugar for waiting for a promise to be resolved.
The only drawback from having a mix of promises and async functions might be readability and maintainability of the code, but you can certainly use the return value of async functions as promises as well as await for regular functions that return a promise.
Whether you choose one vs the other mostly depends on availability (does your node.js / browser support async?) and on your aesthetic preference, but a good rule of thumb (based on my own preference at the time of writing) could be:
If you need to run asynchronous code in series: consider using async/await:
return asyncFunction()
.then(result => f1(result))
.then(result2 => f2(result2));
vs
const result = await asyncFunction();
const result2 = await f1(result);
return await f2(result2);
If you need nested promises: use async/await:
return asyncFunction()
.then(result => {
return f1(result)
.then(result2 => f2(result, result2);
})
vs
const result = await asyncFunction();
const result2 = await f1(result);
return await f2(result, result2);
If you need to run it in parallel: use promises.
return Promise.all(arrayOfIDs.map(id => asyncFn(id)))
It has been suggested you can use await within an expression to await multiple tasks like so:
*note, this still awaits in sequence from left to right, which is OK if you don't expect errors. Otherwise the behaviour is different due to fail fast behaviour of Promise.all()
const [r1, r2, r3] = [await task1, await task2, await task3];
(async function() {
function t1(t) {
console.time(`task ${t}`);
console.log(`start task ${t}`);
return new Promise((resolve, reject) => {
setTimeout(() => {
console.timeEnd(`task ${t}`);
resolve();
}, t);
})
}
console.log('Create Promises');
const task1 = t1(100);
const task2 = t1(200);
const task3 = t1(10);
console.log('Await for each task');
const [r1, r2, r3] = [await task1, await task2, await task3];
console.log('Done');
}())
But as with Promise.all, the parallel promises need to be properly handled in case of an error. You can read more about that here.
Be careful not to confuse the previous code with the following:
let [r1, r2] = [await t1(100), await t2(200)];
function t1(t) {
console.time(`task ${t}`);
console.log(`start task ${t}`);
return new Promise((resolve, reject) => {
setTimeout(() => {
console.timeEnd(`task ${t}`);
resolve();
}, t);
})
}
console.log('Promise');
Promise.all([t1(100), t1(200), t1(10)]).then(async() => {
console.log('Await');
let [r1, r2, r3] = [await t1(100), await t1(200), await t1(10)]
});
Using these two methods is not equivalent. Read more about the difference.
In the end, Promise.all is a cleaner approach that scales better to an arbitrary number of tasks.
Actually it depends on your node version, But if you can use async/await then your code will be more readable and easier to maintain.
When you define a function as 'async' then it returns a native Promise, and when you call it using await it executes Promise.then.
Note:
Put your await calls inside a try/catch, because if the Promise fails it issues 'catch' which you can handle inside the catch block.
try{
let res1 = await your-async-function(parameters);
let res2 = await your-promise-function(parameters);
await your-async-or-promise-function(parameters);
}
catch(ex){
// your error handler goes here
// error is caused by any of your called functions which fails its promise
// this methods breaks your call chain
}
also you can handle your 'catch' like this:
let result = await your-asyncFunction(parameters).catch((error)=>{//your error handler goes here});
this method mentioned does not produce an exception so the execution goes on.
I do not think there is any performance difference between async/await other than the native Promise module implementation.
I would suggest to use bluebird module instead of native promise built into node.
At this point the only reason to use Promises is to call multiple asynchronous jobs using Promise.all() Otherwise you’re usually better with async/await or Observables.
Its depending upon what approach you are good with, both promise and async/await are good, but if you want to write asynchronous code, using synchronous code structure you should use async/await approach.Like following example, a function return user with both Promise or async/await style.
if we use Promise:
function getFirstUser() {
return getUsers().then(function(users) {
return users[0].name;
}).catch(function(err) {
return {
name: 'default user'
};
});
}
if we use aysnc/await
async function getFirstUser() {
try {
let users = await getUsers();
return users[0].name;
} catch (err) {
return {
name: 'default user'
};
}
}
Here in promise approach we need a thenable structure to follow and in async/await approach we use 'await' to hold execution of asynchronous function.
you can checkout this link for more clarity Visit https://medium.com/#bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8
Yesterday I made a tentative decision to switch from using Promises to using Async/Await, independent of nodejs, based on the difficulty in accessing previous values in the Promise chain. I did come up with a compact solution using 'bind' to save values inside the 'then' functions, but Async seemed much nicer (and it was) in allowing direct access to local variables and arguments. And the more obvious advantage of Async/Await is, of course, the elimination of the distracting explicit 'then' functions in favor of a linear notation that looks much like ordinary function calls.
However, my reading today uncovered problems with Async/Await, which derail my decision. I think I'll stick with Promises (possibly using a macro preprocessor to make the 'then' functions look simpler) until Async/Await gets fixed, a few years from now.
Here are the problems I found. I'd love to find out that I am wrong, that these have easy solutions.
Requires an outer try/catch or a final Promise.catch(), otherwise errors and exceptions are lost.
A final await requires either a Promise.then() or an extra outer async function.
Iteration can only be properly done with for/of, not with other iterators.
Await can only wait for only one Promise at a time, not parallel Promises like Promise chains with Promise.all.
Await doesn't support Promise.race(), should it be needed.

How to stop BrowserWindow from breaking after a single error in executeJavaScript?

I'm using the executeJavaScript method to control a page via Electron. However, I've noticed that the BrowserWindow instance essentially becomes unresponsive after one error occurs. Aside from putting every single line of code in a try/catch block, is it possible to disable this functionality?
Specifically, I'd prefer that the BrowserWindow continues to execute future code despite running into an error on a previous request. For example, in the code below, I want the console to successfully output I'm not being executed.
const {BrowserWindow, app} = require('electron')
async function main() {
var win = new BrowserWindow({webPreferences: {nodeIntegration: false} });
win.openDevTools();
win.loadURL('https://www.homedepot.com');
await sleep(10000); //letting page load
await win.webContents.executeJavaScript('console.log("Im being executed")')
await sleep(2000);//break
await win.webContents.executeJavaScript('undefinedVar.causeError()')
await sleep(2000);//break
await win.webContents.executeJavaScript('console.log("Im not being executed")')
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
app.on('ready', main)
First, I don't believe the BrowserWindow is unresponsive after executing the broken code. You can still move it around and maximize it, etc. It's just that the Promise returned by executeJavaScript is stuck in a pending state, and so you never finish awaiting it.
This is actually fixed in Electron 6 by this pull request. In Electron 6, you can do this:
var win;
async function createWindow2() {
win = new BrowserWindow();
win.openDevTools();
await win.loadURL('https://www.google.com');
await executeSafely('console.log("Im being executed")');
await executeSafely('undefinedVar.causeError()');
await executeSafely('console.log("Im not being executed")');
}
async function executeSafely(code) {
try {
await win.webContents.executeJavaScript(code);
}
catch (e) { } // assuming you want to ignore errors
}
If upgrading Electron isn't an option for you, then you can create a function that wraps your code in a Promise, or a try/catch depending on what you need.
If you just want to ignore all errors, then wrapping your executed-code in a try/catch is sufficient. Otherwise, you can wrap in a Promise, which should result in the Promise returned by executeJavaScript being rejected. Example:
async function main() {
var win = new BrowserWindow();
win.openDevTools();
win.loadURL('https://www.google.com');
await sleep(5000);
await win.webContents.executeJavaScript(makeSafe('console.log("Im being executed")'));
await win.webContents.executeJavaScript(makeSafe('undefinedVar.causeError()'));
await win.webContents.executeJavaScript(makeSafe('console.log("Im not being executed")'));
}
function makeSafe(code) {
return "try{" + code + "}catch{}";
}

Why I need to call every function with async keyword for calling an API in modularized code

I have just started with async and await and trying to convert all my callback syntax to async/await style.
One thing I could not understand is, why I need to every time prefix my function with async keyword.
Here is the example:
APIQuery.js
makeRequest: async(options) => {
try {
var response = await(request(options1))
}
catch(err){
console.log("Some error occurred");
response = undefined;
}
return response;
}
MobileAPI.js
getMobileData: async modal => {
var options = {method: 'GET', json: true,uri: 'https://example.com/mobile/'+modal}
var response = await APIQuery.makeRequest(options);
}
MobileService.js
getMobileDataService: async modal => {
var response = await MobileAPI.getMobileData(modal);
}
MobileController.js
Similarly again I have to use async and await combination to return response.
So my question is, is there a way to get rid of using this everywhere. Calling async await inside APIQuery.js is not enough?
If you want to use the await operator, you have to use async keyword before function declaration:
The await operator is used to wait for a Promise. It can only be used inside an async function.
If you don't want to use async everywhere, you can continue using callbacks or Promises (then, catch, etc.).
So my question is, is there a way to get rid of using this everywhere.
You can't block. Period. As soon as you block, your server would become completely unresponsive to all requests until it's unblocked. For this reason, your code must be asynchronous.
Callbacks are a perfectly valid form of asynchrony, but async/await is easier to use, understand, and maintain.

Typescript with Mongoose EXEC() function async/await

I am trying to use Typescript with Express and Mongoose. So far the result has been amazing. I am however stuck at a very minor part.
Premise: I am executing a Mongoose Query using EXEC()
let result = await UserModel.User.find().exec();
I have to use the async / await as there is some processing after this line and I want to avoid callbacks throughout
Problem
I need to get the {err, data} from the result object returned by the query. However currently it simply holds the entire data and I am not able to perform the error handling
So need a way to get the mongoose error description when I use async/await
Error handling using async/await is done by using try/catch:
try {
let result = await UserModel.User.find().exec();
...
} catch(err) {
...
}
Try using the library await-to-js
Example:
const to = require(‘await-to-js’).default
const [err, result] = await to(func())
if (err) throw err
...

Resources