Most of the articles mention that await is a replacement for then. However, I can't find a way to do the approach below by using await since it will defer execution until run query finishes. Just curious, is there a way?
this.database
.run(query, bindings)
.then(result => this.ws.send(result))
.catch(err => this.ws.error(err));
return reply.code(202).send();
The fact that you can't directly use async/await here should tip you off that what you have here isn't such a good idea. It's fire-and-forget code, which is rarely a good practice.
However, if that's actually what you want to do, one option available is to put the async/await in a separate method.
Separate method:
async runQuery(query, bindings) {
try {
const result = await this.database.run(query, bindings);
await this.ws.send(result);
} catch(err) {
await this.ws.error(err);
}
}
Main code:
this.runQuery(query, bindings);
return reply.code(202).send();
Related
In the below code have I createPost() inside an async function, but I don't want to use await on it, so it blocks execution of the rest of the function. That is why I used then.
The outer async function have lots of other functions that use await, so that can't be changed.
Question
Since createPost() is a async/await function (see below). How can it resolve/reject to then/catch in the outer function?
module.exports = async (p) => {
// lots of code here
const t = await function1();
// lots of code here
createPost(p).then(message => {
// lots of code here
console.log("ok " + message);
}).catch(message => {
console.log("failed " + message);
});
};
createPost()
module.exports = async (p) => {
// lots of code here
try {
const r = await getStat();
} catch (error) {
console.log(error);
};
};
async / await is a more modern equivilant to .then / .catch.
In this case you have mixed the syntaxes of both.
You don't need try / catch blocks when using .then,
just like you don't need to declare a function as async when using the try / catch syntax.
Other than that there's no reason they can't work together in seperate functions.
module.exports = (p) => {
createPost(p).then(message => {
console.log("ok " + message);
}).catch(message => {
console.log("failed " + message);
});
};
createPost():
module.exports = async (p) => {
try {
const r = await getStat();
} catch (error) {
console.log(error);
};
};
An async decleration on a function is redundant and wrong if you're not using the await keyword inside.
await/async are often referred to as syntactic sugar, and let us wait for something (e.g. an API call), giving us the illusion that it is synchronous in an actual asynchronous code, which is a great benefit.
The things you want to acheive with async/await is is possible with promises but the advantages of async/await. let's an example with this code:
const makeRequest = () => //promise way
getJSON()
.then(data => {
return data
})
makeRequest();
const makeRequest = async () => { //async await way
const data = await getJSON();
return data;
}
makeRequest()
Why is async/await prefered over promise?
Concise and clean - We didn’t have to write .then and create an anonymous function to handle the response, or give a name data to a variable that we don’t need to use. We also avoided nesting our code. async/await is a lot cleaner.
Error handling - Async/await makes it finally possible to handle both synchronous and asynchronous errors with the same try/catch format.
Debugging - A really good advantage when using async/await is that it’s much easier to debug then promises for 2 reasons: 1) you can’t set breakpoints in arrow functions that return expressions (no body). 2) if you set a breakpoint inside a .then block and use debug shortcuts like step-over, the debugger will not move to the the following .then because it only “steps” through synchronous code.
Error stacks - The error stack returned from promises chain gives us no idea of where the error occured and can be misleading. async/await gives us the error stack from async/await points to the function that contains the error which is a really big advantage.
I heard that promises are supposed to be linear in code in opposed to callbacks ("callback hell").
Though I still have a scenario similar to callback hell and hoping promises can make their promise and have a linear syntax equivalent to this problem code.
Given promises p(), q(),w() consider this code:
p().then(() => {
q().then(() => {
w().then(() => {
// do something
})
})
})
Can we make an equivalent code which is not indented for every nested promise?
You should not nest the .then() handlers but let each .then() create and return a new Promise. This is how it was designed to work, otherwise you are still in the callback hell, now the version with promises. No big difference.
The code should be like this:
p()
.then(() => {
return q();
})
.then(() => {
return w();
})
.then(() => {
// do something
});
If all that the .then() handlers do is to call the next function you can write it in a simpler form (read about arrow functions):
p()
.then(() => q())
.then(() => w())
.then(() => {
// do something
});
Even more, if q and w are called without arguments, the code could be as simple as:
p()
.then(q)
.then(w)
.then(() => {
// do something
});
Or you can go the extra mile and instead of using .then() and .catch() you use await. The code becomes even more clear and easy to read:
try {
await p();
await q();
await w();
// do something
} catch (err) {
// write here the code you would write in the handler you pass to `.catch()
// in the approach that uses Promises
}
Remarks
If the code above, using await, is used in a function then that function must be an async function (just put async in front of its definition).
The code that uses await may or may not be used outside of a function (i.e. at module's top level) depending on the runtime you use to run it (browser, Node.js etc).
As another user mentioned, you could use async/await but another option is just to slightly restructure what you have. Here are some examples of what could work – depending on where and when you need certain pieces of data:
p()
.then(q)
.then(w)
// OR
p()
.then(() => q())
.then(() => w())
Obviously this gets a little more complicated if w() needs data from both p() and q() but that's the gist of it.
You could try using async/await, which leaves a more cleaner code. It would be like this:
(async () => {
try {
await p();
await q();
await w();
} catch (e) {
// handle error
}
})()
If there is no dependency between each promise you can use await Promise.all in order to do "all or nothing". In any other case, you can store the returned value and pass it to the next function in order to be used if needed.
I'm having difficulties understanding ES6 Promises and Async/await.
I looked up for videos on youtube explaining those topics and still my head cannot sink inm what is the difference between them and when should I use Promises over Async/await or Async/await over Promises?
Also when do I know if my code is "valid" promises or async/await.
Here I have two examples (both working) that fetches "companies" from my local JSON server and when it's finished, it loops through those companies.
First example: ( Using Promises )
function getCompanies() {
return new Promise((resolve, reject) => {
fetch(`http://localhost:3000/companies`)
.then(response => response.json())
.then(response => resolve(response))
.catch(error => reject(error))
})
}
function loopCompanies(companies) {
companies.forEach((company) => {
console.log(company);
})
}
getCompanies().then(response => loopCompanies(response)).catch(error => console.log(error));
Second Example: (Using Async/await)
async function getCompanies() {
let response = await fetch(`http://localhost:3000/companies`);
let processedResponse = await response.json();
return processedResponse
}
function loopCompanies(companies) {
companies.forEach((company) => {
console.log(company);
})
}
async function doIt() {
try{
let response = await getCompanies();
loopCompanies(response)
} catch(error) {
console.log(error)
}
}
doIt()
So I wan't know if that's how I should use Promises in Example 1?
Is that how I should use Async/await in Example 2 ?
And what are the differences between them
The first example is unnecessarily wrapping a manually created promise around a promise you already have. This is an anti-pattern for a variety of reasons. You should just return the promise that fetch() already returns. You can do this:
function getCompanies() {
return fetch(`http://localhost:3000/companies`)
.then(response => response.json());
})
}
function loopCompanies(companies) {
companies.forEach((company) => {
console.log(company);
})
}
getCompanies().then(response => loopCompanies(response)).catch(error => console.log(error));
The second example (using async/await) looks fine to me. You can simplify it a bit by changing this:
async function getCompanies() {
let response = await fetch(`http://localhost:3000/companies`);
let processedResponse = await response.json();
return processedResponse
}
to this:
async function getCompanies() {
let response = await fetch(`http://localhost:3000/companies`);
return response.json();
}
As there is no need to await a value you are just going to return. Instead, you can just return the promise directly. Either generates the same result, but the second way does it with less code.
I looked up for videos on youtube explaining those topics and still my head cannot sink inm what is the difference between them and when should I use Promises over Async/await or Async/await over Promises?
async and await absolutely use promises. In fact, await does nothing useful unless you await a promise. And, async functions ALWAYS return a promise. So, async/await are not an alternative to promises. They are an alternative to .then() that gives you a different syntax that is sometimes more friendly to write, debug and read, particularly when you want to sequence multiple asynchronous operations.
Also when do I know if my code is "valid" promises or async/await.
Your code is valid when it delivers the proper result in both success and error conditions and is written without unnecessary steps and without anti-patterns. There's no magic answer beyond that. There is no tool I'm aware of that will tell you that. Just like there's no tool that will tell you if you're 100 line function is written well or not. You have to learn good coding practices for Javascript asynchronous development and then you will recognize good patterns and not-so-good patterns.
So I wan't know if that's how I should use Promises in Example 1?
See my fixed up example above for removing the anti-pattern from Example 1.
Is that how I should use Async/await in Example 2 ?
Yes, that's fine, but it can be simplified further as I showed in my example above.
And what are the differences between them
In my two amended examples, they accomplish the same result. They are just two different coding styles. You can decide which one you prefer. Neither is "more right" than the other.
My personal style is to use async/await when there's a good reason to use it such as:
Multiple asynchronous operations I'm sequencing.
When it leads to simpler, foolproof error handling.
When it leads to simpler looking code.
When I want to make sure synchronous exceptions get caught and turned into a rejected promise.
When I don't need to run in older JS engines that might not support async/await without transpiling.
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.
The following code works just fine. But, I would like to change the Promise code in the middle of the function (indicated by comments) to Async code and replace the for loop with map(). How would I do this?
const main = async () => {
try{
const driver = await new webdriver.Builder()
.withCapabilities(webdriver.Capabilities.chrome())
.setLoggingPrefs(prefs)
.forBrowser('chrome')
.setChromeOptions(options)
.build();
// Start promise code
await driver.findElements(By.css('input'))
.then(function(elements){
for(let i=0; i<elements.length; i++){
elements[i].getAttribute("value")
.then(function(val){
console.log(val);
});
}
})
.catch(function(error){
console.log(error);
});
// End promise code
await driver.quit();
} catch (error) {
console.log(error);
}
};
main();
Since you're merely dumping information to the console, I'd suggest:
// Start promise code
try {
for (let element of await driver.findElements(By.css('input'))){
console.log(await element.getAttribute("value"));
}
} catch (error) {
console.log(error);
}
This shows how async/await nicely recaptures imperative programming, using let in loops.
It differs from your code in that it lists the attributes in order (yours relied on getAttribute timing).
If speed is important, get the attributes in parallel while maintaining order like this:
let elements = await driver.findElements(By.css('input'));
for (let val of await Promise.all(elements.map(e => e.getAttribute("value")))) {
console.log(val);
}
I am guessing that you want to replace some of that promise code with functionally identical code of a different style? If so, here is that code (dubiously) compressed into two lines:
// Start promise code
const elements = await driver.findElements(By.css('input'));
await Promise.all(elements.map(ele => ele.getAttribute('value').then(console.log))).catch(console.log);
// End promise code
You mention that you'd like to replace the promise based code with async/await style code. I'd caution against that in general (although in this instance I think it helps), since async/await is based on promises anyway (so there's no escaping them). Learn to love the promise, and only use the async/await syntax when it really makes the code cleaner.