Asynchrone constructeur

Comment puis-je mieux gérer une situation semblable à la suivante?

J'ai un constructeur qui prend un certain temps pour terminer.

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.

Je vois trois options, chaque de ce qui semble hors de l'ordinaire.

Un, ajouter un rappel du constructeur.

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);
});

Deux, utilisez EventEmitter à émettre un "chargé" de l'événement.

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);
});

Ou trois, de bloquer le constructeur.

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)

Mais je n'ai pas vu tout cela avant.

Ce que d'autres options s'offrent à moi?

  • Le blocage de l'constructeur moyens de blocage tout, donc je ne serais probablement pas le faire.
  • Les Options 1 et 2 sont effectivement la même approche. Vous passez un gestionnaire de chargement pour le constructeur, et que le gestionnaire est déclenchée à partir de l'intérieur de la readFile de rappel. C'est de cette façon basés sur les événements de la programmation de travaux (qui est ce que JavaScript/Nœud). Vous pouvez utiliser l'option 1, ou 2, ou toute autre variation sur le thème, mais efficace, d'obtenir le même comportement asynchrone.
  • J'ai appris beaucoup plus de choses à partir de cette "question" que les réponses données. +1 pour le "informatif question"!
  • Juste une choses. Utilisation .once() pas .on() pour ce cas. C'est sementically mieux :).
  • Je suis à la recherche d'un moyen de le faire bloquer avec ES6 Classes, est-ce possible? Merci
  • Vous devriez pas de bloc. Utiliser des promesses à la place.

InformationsquelleAutor Luke Burns | 2012-08-08