Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
143
rated 0 times [  145] [ 2]  / answers: 1 / hits: 23677  / 12 Years ago, wed, august 8, 2012, 12:00:00

How can I best handle a situation like the following?



I have a constructor that takes a while to complete.



var Element = function Element(name){
this.name = name;
this.nucleus = {};

this.load_nucleus(name); // This might take a second.
}

var oxygen = new Element('oxygen');
console.log(oxygen.nucleus); // Returns {}, because load_nucleus hasn't finished.


I see three options, each of which seem out of the ordinary.



One, add a callback to the constructor.



var Element = function Element(name, fn){
this.name = name;
this.nucleus = {};

this.load_nucleus(name, function(){
fn(); // Now continue.
});
}

Element.prototype.load_nucleus(name, fn){
fs.readFile(name+'.json', function(err, data) {
this.nucleus = JSON.parse(data);
fn();
});
}

var oxygen = new Element('oxygen', function(){
console.log(oxygen.nucleus);
});


Two, use EventEmitter to emit a 'loaded' event.



var Element = function Element(name){
this.name = name;
this.nucleus = {};

this.load_nucleus(name); // This might take a second.
}

Element.prototype.load_nucleus(name){
var self = this;
fs.readFile(name+'.json', function(err, data) {
self.nucleus = JSON.parse(data);
self.emit('loaded');
});
}

util.inherits(Element, events.EventEmitter);

var oxygen = new Element('oxygen');
oxygen.once('loaded', function(){
console.log(this.nucleus);
});


Or three, block the constructor.



var Element = function Element(name){
this.name = name;
this.nucleus = {};

this.load_nucleus(name); // This might take a second.
}

Element.prototype.load_nucleus(name, fn){
this.nucleus = JSON.parse(fs.readFileSync(name+'.json'));
}

var oxygen = new Element('oxygen');
console.log(oxygen.nucleus)


But I haven't seen any of this done before.



What other options do I have?


More From » node.js

 Answers
22

Given the necessity to avoid blocking in Node, the use of events or callbacks isn't so strange(1).



With a slight edit of Two, you could merge it with One:



var Element = function Element(name, fn){
this.name = name;
this.nucleus = {};

if (fn) this.on('loaded', fn);

this.load_nucleus(name); // This might take a second.
}

...


Though, like the fs.readFile in your example, the core Node APIs (at least) often follow the pattern of static functions that expose the instance when the data is ready:



var Element = function Element(name, nucleus) {
this.name = name;
this.nucleus = nucleus;
};

Element.create = function (name, fn) {
fs.readFile(name+'.json', function(err, data) {
var nucleus = err ? null : JSON.parse(data);
fn(err, new Element(name, nucleus));
});
};

Element.create('oxygen', function (err, elem) {
if (!err) {
console.log(elem.name, elem.nucleus);
}
});





(1) It shouldn't take very long to read a JSON file. If it is, perhaps a change in storage system is in order for the data.


[#83774] Tuesday, August 7, 2012, 12 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
kiley

Total Points: 733
Total Questions: 118
Total Answers: 94

Location: Liechtenstein
Member since Wed, Dec 8, 2021
3 Years ago
;