Search code examples
javascriptmethodsfetch-apimethod-chaining

Call an object method once the chained methods are resolved


I would like to create a custom api service that will work similarly to the supabase-js library. Example:

const { data, error } = await supabase
  .from('cities')
  .select('name, countries(*)')
  .eq('countries.name', 'Estonia')

I cannot figure out how it is possible that the last method doesn't have to be something like .get() (which would perform the fetch request)

Ideally, I would like the fetch to be called automatically after the chained methods are resolved - sth. like this:

const { data, pending, error } = await useProductsService()
                                             .whereIn('id', [123, 12, 521, 521])
                                             .whereLowerThan('price', 300)

note: I used supabase just as an example, I want to use this with a completely different API

I know how to do it with sth like a .get() method at the end, however, I'd like to do it without it, if possible. It's not a big deal to have to call one more method but I see it as an opportunity to learn something new as well.

Is it possible to do something like this? Or did I understand something wrong?


Solution

  • As you correctly point out, it is necessary to have a function call at the very end, to let the chain know that you have finished building it and that it's time to execute the DB query.

    However, when you do the destructuring and extract the data property, if there is a getter function for data, then that will act as the function which is called that signals that the building of the query is complete.

    class Chain {
      from(s)   {
        this.config = []; // 'from' is always the first in the chain, so reset the config
        this.config.push({from: s}); return this;
      }
      select(s) { this.config.push({select: s}); return this; }
      eq(s)     { this.config.push({eq: s}); return this; }
      get data() {
        console.log(this.config);
        // do the query here
        return 'this is the result';
      }
    }
    
    const api = new Chain()
    
    const { data } = api
      .from('cities')
      .select('name, countries(*)')
      .eq('countries.name', 'Estonia')
    
    console.log(data)