I’m working on upgrading a library that looks something like this (in coffeescript for conciseness):
//machine.coffee
exports.Machine = class Machine
constructor: (config) ->
/** initialize Machine with config data **/
getSomething: (callback) ->
/** do something that depends on config **/
callback null, something
and is used like you might expect:
machine = require 'machine'
config = {knob: "tweak", switch: "fiddle" }
myMachine = machine.createMachine config
myMachine.getSomething (err, something) ->
/** we now have something **/
However, now the config is dependent upon a setting that I have to request from another site, so it looks more like this, and Machine was updated to parse and use the data from external sources. So accessing Machine like this works:
config = {knob: "tweak", switch: 'http://returns/switch/data' }
/**methods now must wait until Machine is initialized with remote config data **/
machine.createMachine config, (err, machine) ->
machine.getSomething (err, something) ->
/** we now have something **/
But the problem is this breaks the original usage which was:
myMachine = machine.createMachine config
/** remote calls to config not completed yet **/
myMachine.getSomething (err, something) ->
/** we don't have something because Machine is still initializing **/
My question: Is there anyway to preserve the original use case?
One approach might be to queue method calls on the uninitialized class until its fully initialized, but I’m not sure how to even begin doing that. Is there even a way to queue methods? Or are there other better approaches that would allow legacy code with the original usage to still work?
Clarification:
I have no control over the initial config data nor over when or what methods will be subsequently called on Machine. I do have the ability to modify Machine in any way necessary though.
I don’t think you should expose a
Machineconstructor anymore. Rather, you should expose an async factory function: