I create common function that will be called several different times and that function is async/await type.
const storeData = async () => {
await User.create({name: "Test 123"})
}
Now if I want to call function storeData in many different functions asynchronously, do I call it with await in a front of it (option 1 bellow) or since it has async await inside of it, will be run as async function and there is no need for await in front (option 2 bellow)?
(Note: I could do workaround and make storeData to return a new Promise and then do the things inside the promise and be sure that await will really matters.)
Option 1.
async dummy1() {
await storeData();
...rest of thte code
}
Option 2.
async dummy2() {
storeData();
...rest of the code
}
In javascript, all asynchronous functions are identical to a regular function that returns a promise. The async is just syntactic sugar. So, if you use await before the function call, the function call will block execution, and if you don't use await then it'll run asynchronously, like you desire.
Read more here.
Related
I am trying to figure out how to call multiple methods with 1 button click synchronously. My first function is an AJAX call. So it's naturally not synchronous. To solve that issue I have used async-await. Async-await is waiting inside the same function, but not on the other functions that are being called.
I am using Stimulus.js to create classes, but general answer is enough for me: https://stimulusjs.org/
This is what my code looks like:
Button: onClick:
classA#methodA classB#methodB
in class A
async methodA(event){
const response = await axios.post('/url', { data }, options);
const data = await response.json();
doSomething()
}
in class B
methodB(){
updateThings()
}
So what I want to achieve is classA#methodA classB#methodB be called synchronously. But methodA is not waiting for methodB even though methodA is not compete. And even when I am using async await on methodA.
Any idea on how I can solve this issue?
Creating a wrapper method and calling them doesn't seem possible because of the way Stimulus.js works.
In your button click, you should have something like that:
async () => {
await methodA();
await methodB();
}
And also, the both methods should have the async mark:
async methodA(event){
const response = await axios.post('/url', { data }, options);
const data = await response.json();
doSomething()
}
async methodB(){
updateThings()
}
As your methodA is async, the main call to this method by default won't wait it to finish before executing the next lines. So you should explicitly say await methodA().
Check it out:
Understanding async await in javascript
In the code example below function a returns a promise. Using await after return is useless but I thought (and according to the examples) the function returning the promise should still be an async function. However, even if I don't add async keyword to a it still works if it's awaited in function b. If I don't await a() inside b then bRes is a promise object and not 5. So this means that I can have an infinite number of functions like a which return promise and as long as the first function that calls this infinite chain awaits the result, then I don't need to wrap the intermediate functions with async?
const getPromise = () => new Promise((resolve, reject) => {
setTimeout(() => {
console.log('promise finished')
resolve(5)
}, 2000)
})
const a = () => {
console.log('from a')
return getPromise()
}
const b = async () => {
const bRes = await a()
console.log('bRes', bRes)
}
b()
You can only use await inside a function that is async
A function that is async will return a promise
Other means (such as new Promise) can be used to create a promise
You can only (usefully) await a promise
Since a() returns a promise, and b is async, you can await the return value of a() inside b.
No function need to use the async keyword unless the await keyword is used within it.
The await keyword will not work if used outside of functions marked with async. And that's the only technical use of the async keyword (if you want to use it for documentation purposes it's fine but it does nothing otherwise).
All other functions be they synchronous, promise generators, event handlers, observer handlers or just plain old callbacks don't need to be marked with async (unless you use await within them).
I would like to do the following and keep in mind it actually works for me. my question is what happens and Is possible to call async usrs() func from non async componentDidMount() func?
if it is not possible why it is working for me by calling this.usrs(usrs) instead of await this.usrs(usrs);
let outState = {};
class A extends Component{
componentDidMount(){
this.usrs(usrs);
}
getData(usr){
return db.collection('a/'+usr+'/bb').get().then(snap=>{
for(i = snap.docs.length-1; i>=0; i--){
outState[usr] = [...outState[usr], snap.docs[i].data()];
if(i === 0) return outState;
}
return false;
});
}
async usrs(usrs){
let os = {}, data = {};
for(i = usrs.length-1; i>=0; i--){
os = await this.getData(usrs[i]);
if(os){
data = { ...data, ...os };
if (i === 0) {
this.setState({ ...this.state, ...data });
}
}
}
}
}
You only need await if the caller needs to wait for the function to be done, for instance when it needs the result of the function, or when it needs to wait for some state/data change that the function causes. If there is no such dependency, you can just 'fire and forget', by not using the await keyword.
As others mentioned, you could use .then as well, but the basic rule is the same: you do that, when you have something specific to do after the function is done. It can be omitted otherwise.
So concretely: With 'caller', I simply mean the function that calls the async function. In your case that would be componentDidMount. The options are then quite simple:
Keep as is. usrs() will be run in the background completely and componentDidMount will continue running until its end.
Use await, so componentDidMount will wait for the return of usrs().
Use usrs().then(), so componentDidMount can continue, but the code specified in .then() is invoked after usrs() returns, if you need to do something that has to happen after usrs() is done.
We use await when we need to call and wait for async function or Promise
In your case when you call it without await inside your componentDidMount, your function will work but your componentDidMount will not wait for that function to completely finishes.
Also if you don't want to use await and you don't want to wait inside componentDidMount, but you want to get notified when your async function finishes, you can use .then instead. Because async functions returns Promise
Here is your componentDidMount with .then
Notice that in this example this.doSomethingElse will call before the this.usrs is complete, and you only will be notified inside .then about your this.usrs result when it finished:
componentDidMount(){
this.usrs(usrs).then(() => {
// Your functions completely finished
})
.catch(err => {
// There was an error
});
this.doSomethingElse();
}
The async work before the name of the function means that the function always returns a promise, so yes it is possible.
await makes JavaScript wait until the promise is resolved and it pauses when you need to work on the result of that promise.
To understand it better I recommend seeing following page https://javascript.info/async-await
You can call an async function from anywhere.
Async function returns a promise so if you call it like below you can use it as if it was a Promise.
async function example(){
return 10;
}
const returnOfAsync = example()
console.log(returnOfAsync instanceof Promise) // true
returnOfAsync.then((theReturn) => {
console.log(theReturn) // 10
})
Under the hood, an await is simply using a promise (same as a then()), the difference being that it waits for the promise to resolve before continuing execution of the code following it.
So...
Call an async function with await and you will receive the results of the async function after it has completed. Any code that follows the await will execute after the async call returns.
Call an async function without await and you will get a promise as the return value. Code following the await will execute immediately.
If the code that follows the async call requires the value returned from the async call or is dependent on something that happens in the async call, use await. If not, then don't.
My question is how execution wait for function result in node.js or v8
environment.
We know, node.js is single thread non blocking I/O environment.
What is internal code and how it work?
Example async function:
async function asyncCall() {
// `getCreditorId` and `getCreditorAmount` return promise
var creditorId= await getCreditorId();
var creditAmount=await getCreditorAmount(creditorId);
}
If you execute this function then first wait for creditorId then call getCreditorAmount using creditorId and again wait from creditor Amount in this async function only.
Instead of async function other execution not wait, that works fine.
Second question
If use promise for this example
getCreditorId().then((creditorId)=>{
getCreditorAmount(creditorId).then((result)=>{
// here you got the result
})
});
My assumption if async await use promise internally then async must must know which varibale use in getCreditorAmount function as parameter.
How it know ?
Might be my question is worthless?
If it has a answer then i want to know the ans.
Thanks for help.
async-await uses Generators to resolve and wait for Promise.
await is asynchronous in async-await, when compiler reach at await it stops executing and push everything into event queue and continue with synchronous code after async function. Example
function first() {
return new Promise( resolve => {
console.log(2);
resolve(3);
console.log(4);
});
}
async function f(){
console.log(1);
let r = await first();
console.log(r);
}
console.log('a');
f();
console.log('b');
Since await is asynchronous thus every other thing before await happens as usual
a
1
2
4
b
// asynchronous happens
3
async/await is just a Generator.
Take a look at these docs if you would like to learn more.
Generators
Async Function
I'm using sequelize with typescript. I know that the code is asynchronous, and
Here, I am using promise, and the code works..
I would want to know when I must to use await keyword ?
const promises = []
let tabIdDoc = requestedListIdDoc.toString().split(",")
for (let thisIdDoc of tabIdDoc) {
promises.push(sequelize.models['Document'].findById(thisIdDoc))
}
q.all(promises).then((resultReq) => {
const lstDocs = []
for (let MyDoc of resultReq) {
if (MyDoc.matriculeDoc != "") {
lstDocs.push(sequelize.models['FolderDocContent'].findOrCreate({
where: {
}
}))
}
}
q.all(lstDocs).then(() => {
return response.status(201)
})
}
Is await keyword necessary here ?
You don't ever have to use await as other programming using .then() can always get the job done, but there are numerous times when using await makes your code simpler. This is particularly true when you are trying to sequence a number of asynchronous operations and even more so when you need to use previous results in more than one operation that follows.
Example #1: Serializing operations in a for loop
Suppose you want to save a bunch of items to your database, but for various reasons, you need to save them one by one and you need to save them in order (in other words, you need to sequence them):
async function saveItems(shoppingList) {
for (let item of shoppingList) {
// for loop will pause until this promise resolves
await db.save(item);
}
}
saveItems(myList).then(() => {
// all done
}).catch(err => {
// error here
});
Without using await, you'd have to use a significantly more verbose design pattern using .reduce() or perhaps a recursive function that you call on the completion of the prior operation. This is a lot simpler way to sequence iteration of a loop.
Example #2: Sequencing different operations in a function
Suppose, you need to contact three different outside services. You need to get some data from one, then use that data when you make a second API call, then use both of those pieces of data in a third API call:
const rp = require('request-promise');
async function getPrice(productName) {
// look up productID
const productID = await rp(`http://service1.com/api/getID?name=${productName}`);
// use productID to lookup price
const productPrice = await rp(`http://service1.com/api/getPrice?id=${productID}`);
// put both productID and price into the shopping cart
return rp({uri: 'http://service1.com/api/addToCart', body: {name: productName, id: productID}, json: true);
}
getPrice("Nikon_d750").then(total => {
// all done here, total is new cart total
}).catch(err => {
// error here
});
Both of these examples would require more code in order to properly sequence the asynchronous operations and you'd have to nest logic following inside a .then() handler. Using await instructs the JS interpreter to do that nesting for you automatically.
Some other examples here on MDN.
Several rules to keep in mind with await:
You can only use it inside a function prefixed with the async keyword as in my examples above.
All async functions return a promise. If you have an explicit return value in the function as in return x, then that value becomes the resolved value of the promise when all the asynchronous operations are done. Otherwise, it just returns a promise that has an undefined resolved value. So, to use a result from an async function or to know when it's done, you either have to await the result of that function (inside another async function) or you have to use .then() on it.
await only suspends execution within the containing function. It is as if the rest of the code in the function is placed inside an invisible .then() handler and the function will still return its promise immediately when it hits the first await. It does not block the event loop or block other execution outside the async function. This confuses many people when they first encounter await.
If the promise that you await rejects, then it throws an exception within your function. That exception can be caught with try/catch. If it is not caught, then the async function automatically catches it and rejects the promise that the function returns where the thrown value is the reject reason. It is easy when first using await to completely forget about the error cases when promises you are awaiting can reject.
You never necessarily must use await. You however should use await in every place where you'd otherwise have then with a callback, to simplify your code.
In your example:
const promises = requestedListIdDoc.toString().split(",").map(thisIdDoc =>
sequelize.models['Document'].findById(thisIdDoc)
);
const resultReq = await q.all(promises);
const lstDocs = resultReq.filter(myDoc => MyDoc.matriculeDoc != "").map(myDoc =>
sequelize.models['FolderDocContent'].findOrCreate({
where: {}
})
);
await q.all(lstDocs);
return response.status(201)