Ben Aston
Ben Aston

Reputation: 55759

Working with require.js, avoiding newing-up objects repeatedly

Without using something like Require.js I would instantiate things like application client-side controllers when the application loads in the user's web browser. In this way there would remain a single instance of each controller in memory for the lifetime of the application in the browser.

When Require.js is introduced, what is the idiomatic way to achieve the same thing?

Upvotes: 0

Views: 114

Answers (1)

Karolis
Karolis

Reputation: 2959

I would recommend exporting classes in your AMD modules - not instances. E.g.

// controllers/some_controller.js
define(function (require) {
  function SomeController() {};
  SomeController.prototype.foo = function () {};
  return SomeController;
});

And then manage lifecycle of your objects somewhere else, perhaps in your app.js you do something like

// app.js
define(function (require) {

  var SomeController = require("./controllers/some_controller");

  var activeController;

  ...

  router.on("/foo", function () {
    if (activeController) {
      activeController.destroy();
    }
    activeController = new SomeController();
  });
});

Or if you want to have controllers be singletons, like you said, you can do something like this

// app.js
define(function (require) {

  var controllers = {
    "some": require("./controllers/some_controller")
  };
  var controllerCache;

  function getController(name) {
    if (!controllerCache[name]) {
      controllerCache[name] = new controllers[name]();
    }
    return controllerCache[name];
  }

  var activeController;

  ...

  router.on("/foo", function () {
    if (activeController) {
      activeController.exit();
    }
    activeController = getController("some");
  });
});

Anyways, these are pretty convoluted examples, but my main point is that I recommend exporting classes in your modules - not instances - this way you're in control of how you manage those objects and their lifecycle, it also helps testability since you can require the class, stub it, provide mock dependencies, etc. (For more advanced example of using containers to lookup instances of various objects check out http://www.slideshare.net/mixonic/containers-di. He even gives an example of how to use that with AMD modules)

Hope this helps somewhat.

UPDATE Of course, you can also export functions, or objects with functions and whatever else is appropriate, but most likely you don't want to instantiate things or execute things in the top level of your modules - best do it as part of the application flow, not as part of require.js pulling in modules flow..

Upvotes: 2

Related Questions