2

I'm trying to create an JavaScript API client using JavaScript classes. I kind of know how to use JavaScript, but i'm not an expert. I've been reading the developer docs, and my guess is that boxing is occurring, and i'm not sure how to get around it. Every time i try to use the users() i get an exception staying Cannot read property 'client' of undefined which makes me think that when i use this.client in my users() this is undefined. Am I just using JavaScript the wrong way? My code structure is as follows. You can make the assumptions that all the imports required (axios) are included.

class Api {
  constructor(host) {
   this.host = host;
  }
  
  client() {
    return axios.create({
      baseURL: this.host,
      timeout: process.env.API_REQUEST_TIMEOUT,
      headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
    });
  }

  users() {
   return new UserClient(this.client);
  }
}

class UserClient {
  constructor(apiClient) {
    this.client = apiClient;
  }
  
 get() {
   return this.client().get('/users').then(result => result);
 }
}

UPDATE The way i'm use the client is as follows:

const api = new Api('localhost:3000');
api.users().get()

EDIT 2

Added the return statement in the get()

** EDIT 3 ** I kind of figured out what's going on. I'm losing the Api context when using the users() of an Api instance. Adding a console.log(this) in Api#users() returns UserClient and i was expecting it to be Api, and since UserClient doesn't have a client function defined it's returning undefined, so I guess my question is, when i'm using the users() of an Api instance, what's the proper way to maintain the Api context when passing this.client while instantiating a new UserClient?

  • 1
    You need to show us how you are calling the `get` method on the `UserClient` instance since that's almost certainly your problem. Also, highly recommend you name it something other than `get` which could easily be confused (by a human reader, not the language parser) for a getter. Also note that you aren't returning anything from it, and it doesn't seem to be doing anything side-effective with the data returned from the API call. – Jared Smith Jun 26 '20 at 13:33
  • @JaredSmith i updated the question with how i'm using the client. I am returning the values from the functions. i just left it out of the question. Sorry about that. Also, thanks for the naming suggestion. i'm going change it. – davaloseven Jun 26 '20 at 14:06
  • 1
    [I cannot reproduce it](https://jsbin.com/wemozeg/edit?js,console). I don't understand how you'd get this error. Note that `baseURL: this.host,` is likely going to be incorrect as you pass around the method as a function reference and [when you execute it you'll be missing the `this` context](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback/). Yet the error you report is supposed to happen before that and I just can't see it. – VLAZ Jun 26 '20 at 14:23
  • first, it's circular. class Api depends on class UserClient and class UserClient depends on class Api. second, you should use `this.client = new apiClient();` third, you could refactor using inheritance. eg ` class userClient extents Api { constructor() { super(); } ... ` with accompanying edits to de-circularize – Charles Goodwin Jun 26 '20 at 16:10
  • @VLAZ Your linked help tremendously. This is exactly my problem, not understand this in JavaScript. – davaloseven Jun 26 '20 at 16:40

0 Answers0