Reputation: 346
I'm building a package with JavaScript which has two functions: init
and sendData
.
class Client {
init() {
return axios.post(this.baseUrl).then((response) => {
this.token = response.data.token
})
}
sendData() {
return axios.post(this.baseUrl, {token: this.token})
}
}
The init
method needs to be called before the sendData
method as this returns a token. Is there a way to wait for the init method to be called before calling the sendData
method?
Upvotes: 1
Views: 1173
Reputation: 35491
Do you need the consumer of your API to do this?
// within an async function
const client = new Client();
await client.init();
await client.sendDate();
// or anywhere just using promises
const client = new Client();
client.init().then(() => client.sendDate());
or the API itself?
// definition
class Client {
async init() {
const response = await axios.post(this.baseUrl);
this.token = response.data.token;
}
async sendData() {
await this.init(); // call init before sending data
return axios.post(this.baseUrl, {token: this.token})
}
}
// usage somewhere in an async function
const client = new Client();
client.sendDate() // calls init, then sends the data
Maybe remove the redundant calls if the token doesn't change?
class Client {
async init() {
const response = await axios.post(this.baseUrl);
this.token = response.data.token;
}
async sendData() {
if (!this.token) { // now you'll only call init for missing token
await this.init();
}
return axios.post(this.baseUrl, {token: this.token})
}
}
// usage somewhere in an async function
const client = new Client();
await client.sendDate(); // calls init (only the first time), then sends the data
Do note that promise returning functions are inherently asynchronous so there isn't a way of obtaining their result in a synchronous manner. However, we can write the asynchronous code using async/await to make it syntactically look (almost) identical to a synchronous version.
Upvotes: 4
Reputation: 6063
Asynchronous initialization is a good use case for the factory pattern. Instead of doing the asynchronous work after constructing the class, do it before and keep the constructor synchronous. In my opinion a synchronous constructor that does simple assignment has the least "smell" and is the easiest to test.
class Client {
constructor(baseUrl, token) {
this.baseUrl = baseUrl;
this.token = token;
}
async create(baseUrl) {
const response = await axios.post(baseUrl);
return new Client(baseUrl, response.data.token);
}
async sendData() {
return axios.post(this.baseUrl, {token: this.token})
}
}
...
const client = await Client.create('http://foo.com');
const response = await client.sendData();
Upvotes: 0