I have a component which takes some inputs from a user and then does some calculations (which takes some seconds). I want to use async/await block to handle this in UI. Here is the main part of the code:
async function computePV(data) {
return await pv(data);
}
function compute(e) {
console.log("button clicked")
pcvpromise = computePV(data);
console.log("promise created")
}
$: console.log(pcvpromise)
Here function pv() is the one that does the calculations. Method compute() is called by on:click event from button. My expectations:
Show message "button clicked"
Show message "promise created"
Show the created promise
Wait until the calculations are done and resolve the promise
Reality:
Show message "button clicked"
Wait until the calculations are done
Show message "promise created"
Show the created promise
The code is a copy of code from Svelte tutorial about async/await I just changed a couple of minor things. What am I doing wrong?
Related
i want that the two functions with await keyword executes first then the alert() and location.reload should be executed.
async function CompleteUpload(){
await LoadValues();
await UploaderMethod();
alert("Product Added Successfully!");
location.reload();
}
the alert just pops before the 2 await function calls and also the page gets reloaded before these methods are executed.
async function LoadValues(){
prName = document.getElementById('NAMEbox').value;
proc = document.getElementById('PROCbox').value;
}
async function UploaderMethod(){
var uploadTask = firebase.storage().ref("Laptops/Img" + id+".png").put(files[0]);
uploadTask.on('state_changed', function(snapshot){
}, .... //firebase upload data function
the upload CompleteUpload() works perfectly if i don't put alert() and reload at the end.
UPDATED** (after someone answered about returning a promise)
at the end of upload task i wrote this:
return new Promise(function(resolve, reject) {
resolve("yeah");
}
changed the complete upload to:
function CompleteUpload(){
LoadValues();
UploaderMethod().then(Reeeload());
}
function Reeeload(){
alert("Product Added Successfully!");
location.reload();
}
This has absolutely nothing to do with the alert.
Your UploaderMethod is defined as async so it always returns a promise, but that promise resolves before the uploadTask is complete (so it continues to the next statement (the alert followed by the reload) immediately).
You should:
Remove the async keyword from it (because it isn't awaiting any promises)
Return a promise created with the Promise constructor
Resolve that promise inside the state_changed event handler (when everything is resolved).
See How do I convert an existing callback API to promises?.
Aside: LoadValues does nothing except entirely synchronous DOM accesses. It shouldn't be marked as async and you shouldn't await the result.
Is it specifically alert() that doesn't work with async/await? What if you replace the alert() and location.reload() lines with something like console.log to see if that executes first as well.
It might be your LoadValues() and UploaderMethod() causing the problems.
await won’t work in the top-level code
so intead of function(){ } use this ()=>{} and it will work
i made the screenshot from this site. i hade the same trouble (https://javascript.info/async-await)enter image description here
I have a function that makes calls to multiple asynchronous functions.
$("#signUpForm").validator().on("submit", function(event) {
if (event.isDefaultPrevented()) {
// handle the invalid form...
sformError();
ssubmitMSG(false, "Please fill all fields!");
} else {
// everything looks good!
event.preventDefault();
//create use when form is submit
ssubmitForm();
//send email verification
sendEmailVerification();
//sign out the user
signOut();
}
});
the functions ssubmitForm() , sendEmailVerification() and SignOut() are all declared asynchronous and all have await statements in them.
I am getting weird behavior that seems to signal to me that these three functions are not running in the order they are written in the code. I thought that with asynchronous code all other code pauses execution and waits for the await statement to finish. But from my logs, I neah function it doesn't seem so. Is this behavior only within the scope of the asynchronous function itself? What is the execution order of the three functions? Can sendEmailVerification() be called before ssubmitForm() is done execution?
Also, I'm not sure if I'm using the correct verbiage/vocabulary to describe my problem. This has been a big problem for me as I am not easily able to search for my issues if I don't know the vocab. Please feel free to correct me on any misuse of terminology.
They are started in the order that they are called, but because they are async, they might not run in the order they are called. They return immediately and return an unresolved Promise, which will eventually resolve (or reject) asynchronously when the called function completes.
You need to mark your function async and await each of the calls in turn:
$("#signUpForm").validator().on("submit", async function(event) {
if (event.isDefaultPrevented()) {
// handle the invalid form...
sformError();
ssubmitMSG(false, "Please fill all fields!");
} else {
// everything looks good!
event.preventDefault();
//create use when form is submit
await ssubmitForm();
//send email verification
await sendEmailVerification();
//sign out the user
await signOut();
}
});
To better understand async/await, I recommend learning about promises first. They are the underlying model that makes everything tick; async/await is just syntactic sugar on top.
I have multiple jQuery click event handlers, each that run asynchronous code (i.e. AJAX call) when clicked.
I have some code like this:
$(selector1).click((e) => {
asyncCode1();
)};
$(selector2).click((e) => {
asyncCode2();
)};
$(selector3).click((e) => {
asyncCode3();
)};
$(selector1).click(); // runs asyncCode1()
$(selector2).click(); // runs asyncCode2()
$(selector3).click(); // runs asyncCode3()
I want $(selector2).click() to run only after $(selector1).click() has completed execution, since asyncCode1() generates elements in the DOM that will eventually be selected in $(selector2).
Should I be returning promises on each of the click handlers? I'm not sure about best practices and how to go about doing this.
Yes, you can do it with Promise. Like this:
let asyncCode1Promise;
$(selector1).click((e) => {
asyncCode1Promise = asyncCode1(); // no await here!
)};
$(selector2).click(async (e) => {
await asyncCode1Promise;
asyncCode2();
)};
async asyncCode1() {
...
}
...
In that case, clicking selector2 will wait for completing code1 (if it's not complete yet). And if it was complete before clicking selector2, then asyncCode2 will run without any delay.
The good thing about using promises is that you can click selector2 multiple times, and it will work as expected (all clicks which are done before completion asyncCode1 will wait for its completion, and all clicks after asyncCode1 finished will call asyncCode2 immediately).
I am trying to understand the mechanism of async functions. I found some code on MDN docs MDN docs, made some modifications and... cannot fully understand how it works.
var resolveAfter2Seconds = function() {
console.log("starting slow promise");
return new Promise(resolve => {
setTimeout(function() {
resolve(20);
console.log("slow promise is done");
}, 6000);
});
};
var resolveAfter1Second = function() {
console.log("starting fast promise");
return new Promise(resolve => {
setTimeout(function() {
resolve(10);
console.log("fast promise is done");
}, 4000);
});
};
var sequentialStart = async function() {
console.log('==SEQUENTIAL START==');
const slow = await resolveAfter2Seconds();
const fast = await resolveAfter1Second();
console.log(fast);
console.log('why?');
console.log(slow);
}
sequentialStart();
For now I know that if we run this code we will immediately receive '==SEQUENTIAL START==' on the console, then "starting slow promise" then we have a Promise with setTimeout which indicates that 'slow promise is done' will appear after 6 seconds and the resolve(20) callback will be kept in api container since execution stack will be empty.JS gives us 'starting fast promise' and after four seconds we get 'fast promise is done' and then immediately 10, 'why?', 20.
I do not understand: what happens in the background exactly - I know that resolve(20) is kept in api container and the rest of the code are executed, then resolve(10) is also kept in api container and when the execution stack is empty they are returned as the results of resolving their Promises.
But:
What with the timer? 10,why,20 appears long after their timeout passes - resolve 20 appears on the screen long after 6 seconds.
What with order? It seems like they (resolve20 and resolve 10) are ready to be executed and kept in memory until I use them - print them in console in this case? TIME APPEARING and ORDER
I am very determined to understand it correctly.
Perhaps this will help clear things up. Async-await is just syntactic sugar, so your sequentialStart function is the exact same thing as:
var sequentialStart = function() {
console.log('==SEQUENTIAL START==');
resolveAfter2Seconds().then(function(slow) {
resolveAfter1Second().then(function(fast) {
console.log(fast);
console.log('why?');
console.log(slow);
});
});
}
I know that resolve(20) is kept in api container and the rest of the code are executed, then resolve(10) is also kept in api container and when the execution stack is empty they are returned as the results of resolving their Promises
That's not what's happening when using async-await, what your code is doing is the following in this specific order:
Call resolveAfter2Seconds()
await it to resolve and then assign the resolved value to the constant slow
Call resolveAfter1Second()
await it to resolve and then assign the resolved value to the constant fast
Call console.log(fast), then console.log('why?'), then console.log(slow)
It seems like you're expecting the promises to resolve in parallel, as they would if you weren't using async-await but the whole purpose of async-await is to be able to write code with promises as if it was synchronous (i.e. blocking) code without creating a nested mess of then callbacks.
I´m using a function for which will animate some things, for example:
function doMyStuff(){
$('#test1').animate({...}, {queue:false});
$('#test2').animate({...}, {queue:false});
return true;
}
// this should only go on if doMyStuff() is complete
doMyStuff();
alert("We can go on, doMyStuff() is finished");
I only want to go on, if this function is finished with his animation. How can I do this? Currently it doesn´t wait for the end of the animation.
Make use of promises:
function doMyStuff(){
return $.when(
$('#test1').animate({...}, {queue:false}).promise(),
$('#test2').animate({...}, {queue:false}).promise()
);
}
doMyStuff().then(function() {
alert("We can go on, doMyStuff() is finished");
});
All the code you want to execute after the animations finished has to be invoked from the callback that is passed to .then.
From the .promise documentation (emphasis mine):
The .promise() method returns a dynamically generated Promise that is resolved once all actions of a certain type bound to the collection, queued or not, have ended.
By default, type is "fx", which means the returned Promise is resolved when all animations of the selected elements have completed.
$.when simply creates a new promise which is resolved when all promises passed to it are resolved.