ES6 Singleton vs Instantiating a Class once

I would recommend neither. This is totally overcomplicated. If you only need one object, do not use the class syntax! Just go for

import Constants from '../constants';

export default {
  url: Constants.API_URL,
  getCities() {
    return fetch(this.url, { method: 'get' }).then(response => response.json());
  }
};

import API from './services/api-service'

or even simpler

import Constants from '../constants';

export const url = Constants.API_URL;
export function getCities() {
  return fetch(url, { method: 'get' }).then(response => response.json());
}

import * as API from './services/api-service'

Both are different ways. Exporting a class like as below

const APIobj = new _API();
export default APIobj;   //shortcut=> export new _API()

and then importing like as below in multiple files would point to same instance and a way of creating Singleton pattern.

import APIobj from './services/api-service'

Whereas the other way of exporting the class directly is not singleton as in the file where we are importing we need to new up the class and this will create a separate instance for each newing up Exporting class only:

export default API;

Importing class and newing up

import API from './services/api-service';
let api = new API()

Another reason to use Singleton Pattern is in some frameworks (like Polymer 1.0) you can't use export syntax.
That's why second option (Singleton pattern) is more useful, for me.

Hope it helps.


The difference is if you want to test things.

Say you have api.spec.js test file. And that your API thingy has one dependency, like those Constants.

Specifically, constructor in both your versions takes one parameter, your Constants import.

So your constructor looks like this:

class API {
    constructor(constants) {
      this.API_URL = constants.API_URL;
    }
    ...
}



// single-instance method first
import API from './api';
describe('Single Instance', () => {
    it('should take Constants as parameter', () => {
        const mockConstants = {
            API_URL: "fake_url"
        }
        const api = new API(mockConstants); // all good, you provided mock here.
    });
});

Now, with exporting instance, there's no mocking.

import API from './api';
describe('Singleton', () => {
    it('should let us mock the constants somehow', () => {
        const mockConstants = {
            API_URL: "fake_url"
        }
        // erm... now what?
    });
});

With instantiated object exported, you can't (easily and sanely) change its behavior.