Reputation: 6338
I know this is a terrible idea. But I have an API which I can't use until I have a piece of data which I can only get asynchronously. Something like this:
const key = await get_async_data(config) // NOT RIGHT, can't use await at top level
const api = new API(key)
... use api ...
This is at top level, outside of any function, so I can't just await get_async_data() (it does return a Promise). Is there anything short of putting all my code in a giant async function so I can call await?
API
is just a class exported by a module (which I control).
(BTW I thought of putting the code to get the key into the API
class's constructor, but of course constructors can't be async either.)
I could make every async method of API
set the key if unset, but that's pretty invasive and error-prone.
So I'm not really asking how to make my top-level code wait as much as I'm looking for alternative ways to structure this so the async call happens cleanly.
Here's some more detail in case this helps. In api.js:
class API {
constructor(key) {
this.key = key
// other stuff
}
async f1(a) {
}
async f2(b, c) {
}
f3() {
return true
}
}
export default API
Then in the places (many) where it'll be used:
import API from '@/api'
const key = async get_key() // NOPE
const theAPI = new API(key)
async importantMethod(args)
{
return await theAPI.f1(args)
}
async otherMethod()
{
if (theAPI.f3)
return await theAPI.f2(123)
// etc...
}
// ... and so on
Upvotes: 3
Views: 2851
Reputation: 370859
If you want to alter your existing code as little as possible, I'd consider changing the entry point to a module which gets the key, and then calls the module which instantiates the API (the old entry point). For example:
// start.js
import makeApi from './makeApi';
get_key()
.then(makeApi);
// makeApi.js
export default function(key) {
const theApi = new API(key);
function importantMethod(args) {
return theAPI.f1(args)
}
function otherMethod() {
if (theAPI.f3)
return theAPI.f2(123)
}
// etc
}
In short, all you have to do is wrap your current entry point in a function.
Upvotes: 0
Reputation: 21936
Just use the Promise:
const pendingAPI = get_async_data(config).then(key => new API(key)); // N.B. no await
export default pendingAPI;
Meanwhile, in another file...
import pendingAPI from 'other/file';
pendingAPI.then(doStuffWithAPI);
There are times when async/await
is a win. But never forget it's just sugar over Promises.
Upvotes: 1
Reputation: 179
top level is a terrible idea, yes. But I don't see why you can't just put it in a function?
const getAsync = async () => {
const key = await get_async_data(config);
return key;
}
getAsync().then(key => {
const api = new API(key)
}
Upvotes: 0