I am building off of a forked React app. There is a dependency module that relies on a couple of static json files to map and export a couple of consts that are consumed in the app's React components. Instead of relying on these static json files, we're using an API as our source. Right now my build process is to fetch the json and transform it to generate our custom json files, which then gets consumed during the build process.
Instead, I want the process to be performed client side.
export const GALAXY = async () => {
const result = await fetch(JSON
, {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
if (result.ok) {
console.log('GALAXY LOADED')
return result.json();
} else {
console.log('GALAXY FAILED')
return undefined
}
}
It seems that anything that relies on an async/await function will only return a Promise. From the docs:
Return resolved promise from async function
Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.
Most of the examples I've found show some variation of the .then pattern:
const galaxy = Promise.resolve(GALAXY()).then((value) => {
console.log(value);
});
but if I try
const galaxy = Promise.resolve(GALAXY()).then((value) => {
return value
});
console.log(galaxy);
I get Promise{pending}
I'm hoping to avoid rewriting a bunch of non-async code. We've got one TS file that gets imported by a number of React components:
import TokenMints from './token-mints.json';
export const TOKEN_MINTS: Array<{
address: PublicKey;
name: string;
}> = TokenMints.map((mint) => {
return {
address: new PublicKey(mint.address),
name: mint.name,
};
});
So how can I fetch from the JSON API and pass the data to this non-async const so that it can be used in the rest of the app?
If you have something like this:
const example = async () => {
return true
}
Then anywhere you call it or use it will result in a promise, that's how async works.
example().then(() => {
// any code here will execute after the promise resolved
}
// any code here can not directly use the promise data as it's not resolved yet.
The code inside then and outside then will execute in parallel, or at least the code outside it will continue executing while the promise resolves and once it finally resolves it will execute the code inside the then.
Alternatively you can use await.
const data = await example() // this forces all code execution to wait for the promise to resolve
// code here will not execute until that promise resolved
You have to correctly use async/await.
Several possibilities to consider
Fetch the JSON using a synchronous XMLHttpRequest operation. Use of this kind of synchronous requests in the main thread is, however, frowned upon (note).
Convert the JSON to JavaScript source on the server (if required, in many/most cases JSON is valid JavaScript), assign it to a global variable and include it in the head section of the client page using <script> tags.
A variation of (2): convert the JSON to a module file on the server which exports the JSON data converted to JavaScipt source, which client code includes as a module, and from which imports the data as a JavaScript object.
If the client code uses the data after waiting for an event such as DOMContentLoaded (then calling a main function rather than writing the app in file level code), you could promisify the DomContentLoaded event arrival, and pass it through Promise.all along with the galaxy promise before calling main, along the lines of
Promise.all(
new Promise( resolve=>
document.addEventListener("DOMContentLoaded", resolve)
),
galaxy
).then( data => main( data[1])); // passing galaxy value
About async
As already noticed, async functions return a promise for the value syntactically returned in the function body - because async functions return synchronously when called, without waiting for any asynchronous operations performed in the function body to complete. Given JavaScript is single threaded, the caller is not put on hold until all operations have been carried out, and must return to the event loop for other pieces of JavaScript code to execute.