Javascript await a function inside an async function - javascript

I have the following codes:
function test1() {
test2.execute();
}
I am trying to use await inside an async function to make test1() execute first:
it("title", async () => {
await test1();
await firebase.assertSucceeds(true);
})
But somehow the function test1() does not execute before firebase.assertSucceeds(true). test1() returns a callback. I tried to use the callback, and it does not help either.
function test1() {
test2.execute().then(() => {
return;
});
}
it("title", async () => {
let x = await test1();
await firebase.assertSucceeds(true);
})
Still synchronous. what did I do wrong here?

In your first snippet you are awaiting for test1 which returns void (nothing), for the await to work it should be applyed to a promise, you acheive that either by returning test2.execute() which returns a Promise :
function test1() {
return test2.execute();
}
or by making test1 async and await for test2 to finish executing :
async function test1() {
await test2.execute();
}
ps: an async function returns a resolved promise with the return as the resolution value so for example :
async function test(){
return 2;
}
is translated under the hood to this:
function test(){
return Promise.resolve(2);
}

A function has to return a Promise if you want to await it.
For example:
function test1() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("I'm done")
}, 500)
})
}
Notice, in the firebase documentation, that assertSucceeds only takes a promise as it's one and only argument. So consider passing it a promise that always resolves if that's what you're going for to begin with.
await firebase.assertSucceeds(Promise.resolve())

Related

await not doing what I expect

async function doThings() {
async function timer () {
setTimeout(() => {
console.log('timer!')
}), 1000
}
async function printer () {
console.log('printer!')
}
await timer()
await printer()
}
doThings()
I thought making the function async made it return a promise and await made it wait. Why does printer() finish first?
Your timer function doesn't work because setTimeout does not return a promise that could be awaited. You will need to promisify it manually:
// set a default of 1500
function timeout(ms=1500) {
return new Promise(resolve => setTimeout(resolve, ms));
};
async function printer() {
console.log('printer!');
};
async function doThings() {
await timeout(1000); // time in ms
await printer();
};
doThings();
The word “async” before a function means one simple thing: a function always returns a Promise. Other values are wrapped in a resolved Promise automatically.
Now when we use don't return Promise from async function, then javascript interpreter automatically returns resolved Promise, so that is the reason await on timer function got the resolved Promise and interpreter went ahead with the execution, but there is a setTimeout still going on. So we have to return a Promise from timer function, and resolve it inside setTimeout function like below.
async function doThings() {
async function timer() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`timer!`);
resolve();
}, 1000)
});
}
async function printer() {
console.log('printer!')
}
await timer()
await printer()
}
doThings()
All I can see is timer () and printer () functions are async functions but there is no await used in them, and this makes the async keyword unfunctional.

return async function undefined in es6

Here, plcs variable within try catch function need to be used outside. I am trying calling async function directly and storing in sync function, both doesn't work, first method shows undefined and next one returns null promise
const fetch = () =>{
const result=async()=>{
try {
const dbResult = await ftchplc();
plcs= dbResult.rows._array;
return plcs
} catch (err) {
throw err;
}
}
return result()
}
const sample = fetch()
console.log(sample)
const result=async()=>{
try {
const dbResult = await ftchplc();
plcs= dbResult.rows._array;
return plcs
} catch (err) {
throw err;
}
}
result()
const sample = result()
ALL async functions return a promise. So you will have to use await or .then() when you call an async function in order to get the resolved value.
async functions are useful INSIDE the function so you can use await internal to the function, but to the outside caller, it's still just a promise being returned. async functions to not turn an asynchronous result into a synchronous result. The caller of an async function still has to deal with an asynchronous response (in a promise).
For example:
async function fn() {
const dbResult = await ftchplc();
return dbResult.rows._array;
};
fn().then(sample => {
console.log(sample);
}).catch(err => {
console.log(err);
});
This assumes that ftchplc() returns a promise that resolves to your expected dbResult.

Calling async function from within async function returns undefined

(Forgive me if the title is inaccurate to the problem this one is boggling the mind)
My application requires that I check a value from the request against the database. For this I created an asynchronous function to query the database:
async function checktoken(){
return prisma.$exists.invalidtoken({token: "testtoken"}).then(result => {
return(result)
})
}
I know that the database call on its own works:
prisma.$exists.invalidtoken({token: "testtoken"}).then(result => {
console.log(result) // returns true
})
In the function that fires at every request I try and call checktoken():
async function getUser(token){
var promise = await checktoken()
var result = promise
console.log(result) //undefined
};
Amending the function to include an explicit call to the database works but only when var promise = await checktoken() is defined before it:
async function getUser(token){
var promise = await checktoken() //When this is removed result1 is undefinded
await prisma.$exists.invalidtoken({token: "testtoken"}).then(result1 => {
console.log("inside db call: "+result1) // true
})
};
I think I have a fundamental misunderstanding of async/await but I am not sure exactly what I am missing.
EDIT:
I have updated my approach taking the advice I received and it still does not work. I am beginning to think my ORM is doing something weird:
async function test(token) {
const status = await prisma.$exists.invalidtoken({ token: token });
console.log(status);
return status;
}
test("123") //logs false (as it should)
async function getUser(token){
var status = await test(token) //logs undefined
console.log(status) //logs undefined
};
An async function requires an await. If you are using the promise.then() technique, then what you would want to do is return a new Promise(), and within the .then call back function resolve the promise
function checktoken() {
return new Promise((resolve,reject) => {
prisma.$exists.invalidtoken({token: "testtoken"}).then(result => {
doSomeOtherStuff();
resolve(result);
});
});
}
Is functionally the same as
async checktoken() {
await prisma.$exists.invalidtoken({token: "testtoken"});
}

Writing async/await version of a promise

The code below logs 'hello world' once in a second as expected.
function moveOneStep() {
return new Promise((res, rej) => {
setTimeout(() => {
res(console.log('Hello world!'))
}, 1000)
})
}
async function main() {
await moveOneStep();
await moveOneStep();
await moveOneStep();
await moveOneStep();
}
Considering the return value of an async function corresponds to what is returned from resolve function in promises, why doesn't the code below output the same result, but instead logs all the 'hello world's at once:
async function moveOneStepAsync() {
setTimeout(() => {
return console.log('Hello world!');
}, 1000);
}
async function main() {
await moveOneStepAsync();
await moveOneStepAsync();
await moveOneStepAsync();
await moveOneStepAsync();
}
That's because setTimeout does not return promise to await it in your main function. setTimeout itself executes synchronously. It adds to an event loop the callback that is passed as an argument to execute in time that is mentioned.
Also in this code return of your callback means nothing as callback with be run in 1 sec and the returned value will go nowhere.
async keyword tells you that functions returns promise and could have awaitable code in it. So as there is not await in your code it then looks like
function moveOneStepAsync() {
setTimeout(() => {
return console.log('Hello world!');
}, 1000);
return Promise.resolve();
}
So your await in main will await one event loop tick to go to the next "step"
Read about setTimeout, event loop, and what await expects to understand it more in-depth
You do not return anything to the function, you return back to the internal setTimeout function, and that does not do anything with that value. Calling setTimeout does not return a promise, it rather returns a timer immeadiately. And therefore all the moveOneStepAsync calls execute immeadiately, the timers get set, and fire after one second.

Await for an async function

Is there a way to await for an async function? Something like yield* (with an asterisk) will delegate to another generator function.
For example:
asyncFunction1 = async () => {
await promise1;
await promise2;
}
asyncFunction2 = async () => {
await asyncFunction1(); // can we do that or it MUST be a promise?
}
Marking a function async makes it implicitly return a promise:
When an async function is called, it returns a Promise. When the async function returns a value, the Promise will be resolved with the returned value. When the async function throws an exception or some value, the Promise will be rejected with the thrown value.
(source)
In other words, you can await on an async function, even when that function returns a non-Promise value (because that value will be wrapped with a Promise automatically):
async function test() {
return 123;
}
void async function() {
let value = await test();
console.log('value', value);
}();

Categories

Resources