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);
}();
Related
I must be missing something here because I do not understand why my promise is not resolving.
I boiled the code down to this simple example:
...
console.log("before");
const promise = second();
console.log("after");
console.log(promise);
...
async function first() {
const p1 = await axios.get("https://<url>");
console.log("first");
console.log(p1.data);
return (p1);
}
async function second() {
const p2 = await first();
console.log("second");
console.log(p2.data);
return (p2);
};
Which produces this output in the console:
before
after
Promise { <pending> }
first
p1.data
second
p2.data
My understanding is that await pauses execution until it completes before moving to the next line, but that is clearly not happening.
The initial block completes with a pending promise, and then the awaited code in the async functions executes instead of pausing.
What am I missing to make my code pause and wait until the await lines complete with a resolved promise before continuing?
In JavaScript, all of the following are true:
A promise
Is a value (can be passed around to functions, assigned to variables, and so on)
Can be in the resolved, rejected, or pending states
The thing it resolves to is also a value (1, "foo", {}, ...)
Can have .then(...) callbacks chained to it
Can be awaited
An async function
Is a function that synchronously returns a promise
Is a function that asynchronously returns the resolved value of that promise
Hopefully this modified example will make it clearer:
// mock axios
const axios = {
get: url => Promise.resolve({ data: `Some data from ${url}` })
}
const fetchMockData = async () => {
const val = await axios.get('https://<url>')
return val
}
const withAsyncAwait = async () => {
console.log('=== with async/await ===')
const promise = fetchMockData() // not awaited
console.log('type of promise:', promise.constructor.name)
const resolved = await promise // here we await it
console.log('type of resolved:', resolved.constructor.name)
console.log('data:', resolved.data)
}
// equivalent but with `then` callback
const withThenCallback = () => {
console.log('=== with then callback ===')
const promise = fetchMockData() // not awaited
console.log('type of promise:', promise.constructor.name)
promise.then(resolved => { // resolved thanks to `then`
console.log('type of resolved:', resolved.constructor.name)
console.log('data:', resolved.data)
})
}
setTimeout(withAsyncAwait, 0)
setTimeout(withThenCallback, 100)
async function is not actually an synchronouse function like we think of, its an promise. So you need to handle it like an promise like:
console.log("before");
second().then(res => {
console.log("after");
console.log(res);
});
An async function is like a Promise which does not resolve immediately. So you should probably use an immediately invoked anonymous async function:
(async()=>{
console.log("before");
const promise = await second();
console.log("after");
console.log(promise);
})();
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())
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.
I'm using a helper function (fetchGet) returning an asynchronous function that returns a promise (fetchWrapper).
Does this helper function need to be declared as asynchronous to itself return a promise?
My case here is using fetch, which needs to be awaited in my first function fetchWrapper (simplified here for readibility):
// returns a promise
async function fetchWrapper(url, method) {
const response = await fetch(url, {method: method});
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response;
}
async function fetchGet(url) {
return fetchWrapper(url, 'GET');
}
async function getSpecificData() {
return fetchGet('/a/specific/url');
}
Do I need to declare the fetchGet function as an asynchronous function as above, for it to return the promise?
Or could I just declare it as a normal synchronous function as below?
(that would be indeed the same case for the getSpecificData function)
function fetchGet(url) {
return fetchWrapper(url, 'GET');
}
Does a function need to be declared as asynchronous to return a promise?
No, not at all. In fact, promises were around long before async functions.
Your wrapper can be just:
function fetchGet(url) {
return fetchWrapper(url, 'GET');
}
You don't need async if you're not using await inside the function. You might choose to have it in order to flag up the asynchronous nature of the function, e.g., as in-code documentation (code hints in IDEs, etc.). But it isn't required.
Side note: You have a problem with fetchWrapper. It succeeds with the fulfillment value undefined if there's an HTTP error. That means code using it has to check the fulfillment value to see if it's undefined before using it. I'd recommend making HTTP errors errors (rejections):
async function fetchWrapper(url, method) {
const response = await fetch(url, {method: method});
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response;
}
Does this helper function need to be declared as asynchronous to itself return a promise?
No.
async functions always return promises, even if the return statement returns something that is not a promise. async functions let you manage other promises inside them using await
You can explicitly return a promise from any function.
You just need to declare a function as async when inside the function you going to await for a result, so both:
// returns a Promise because it's async (resolved with 'value')
async function fetchGet(url) {
const value = await fetchWrapper(url, 'GET');
return value;
}
// returns a Promise because fetchWrapper is a Promise
function fetchGet(url) {
return fetchWrapper(url, 'GET');
}
// returns a Promise, just because it's async
async function fetchGet(url) {
// nothing
}
// returns undefined
function fetchGet(url) {
// nothing
}
Work exactly the same for these callers:
fetchGet('url').then(value => {...})
const value = await fetchGet(url)
In my case , i am able to get the token but not the way i wanted ie i do not want to print promise pending and my output after running in tokenDisp.js is :
output: Promise { pending }
t5Npxk5FfnRTj8iHd8vyyfGxnhXR4KQf
login.js:
module.exports = async function doLogin() {
const token = await loginToken();
const myToken = JSON.parse(token);
return console.log(myToken);
};
tokenDisp.js:
const myToken = require('./login.js);
myToken();
Can someone help ?
All async functions return a promise and you still have to use .then() or await on the return value from the async function in order to use that. If you return a value from your async function, it will be the resolved value of the returned promise. If you throw an exception, the exception will be the reason for the rejection of the returned promise.
The use of await inside the function is a convenience INSIDE the async function. It does not magically make an asychronous operation into a synchronous one. So, your function returns a promise. To get the value out of it, use .then() on it.
module.exports = async function doLogin() {
const token = await loginToken();
const myToken = JSON.parse(token);
console.log(myToken);
return myToken; // this will be resolved value of returned promise
};
const myToken = require('./login.js);
myToken().then(token => {
// got token here
}).catch(err => {
console.log(err);
});
Note: your login.js module produces the same result as if it was written like this (without using async or await):
module.exports = function doLogin() {
return loginToken().then(token => {
const myToken = JSON.parse(token);
console.log(myToken);
return myToken; // this will be resolved value of returned promise
});
};