2016-03-27 1 views
3

J'ai une classe ES2015 qui se connecte à un service distant.Dans ES2015, comment puis-je m'assurer que toutes les méthodes attendent l'initialisation de l'objet? Avec les décorateurs ES7?

Le problème est que mon code essaie d'accéder à cette classe avant que son objet ait fini de se connecter au serveur distant.

Je veux m'assurer que les méthodes ne donnent pas seulement une erreur si l'objet n'a pas fini de s'initialiser.

Je vais avoir beaucoup de méthodes dans ma classe qui dépendent de la connexion en cours, donc ce serait bien s'il y avait un seul mécanisme facile à comprendre qui pourrait être appliqué à toutes les méthodes comme @ensureConnected décorateur.

Fiddle ici: https://jsfiddle.net/mct6ss19/2/

'use strict'; 

class Server { 
    helloWorld() { 
     return "Hello world" 
    } 
} 

class Client { 
    constructor() { 
      this.connection = null 
      this.establishConnection() 
    } 

    establishConnection() { 
     // simulate slow connection setup by initializing after 2 seconds 
     setTimeout(() => {this.connection= new Server()}, 2000) 
    } 

    doSomethingRemote() { 
      console.log(this.connection.helloWorld()) 
    } 

} 

let test = new Client(); 
// doesn't work because we try immediately after object initialization 
test.doSomethingRemote(); 
// works because the object has had time to initialize 
setTimeout(() => {test.doSomethingRemote()}, 3000) 

j'imagerie à l'aide décorateurs ES7 pour mettre en œuvre un test pour voir si la connexion est établie, mais je ne vois pas comment le faire.

+0

Ajoutez un paramètre de rappel à votre constructeur client, transmettez-lui une fonction de rappel, appelez cette fonction après que le serveur a répondu et appelez les autres méthodes client depuis le rappel. –

+0

FYI, les décorateurs ne font pas partie de ES7 (ES2016). –

+1

related: [Est-ce une mauvaise pratique d'avoir une fonction constructeur renvoyer une promesse?] (Http://stackoverflow.com/q/24398699/1048572) - créez vos instances seulement lorsqu'elles sont prêtes. – Bergi

Répondre

3

Je ne voudrais pas initier la connexion dans le constructeur. Les constructeurs sont plus conçus pour l'initialisation des variables, etc., que pour la logique du programme. Je voudrais plutôt appeler establishConnection vous-même à partir de votre code client.

Si vous voulez faire dans le constructeur, stocker le résultat dans une variable d'instance, puis attendre dans doSomethingRemote, comme dans:

class Client { 
    constructor() { 
     this.connection = this.establishConnection(); 
    } 

    establishConnection() { 
     // simulate slow connection setup by initializing after 2 seconds 
     return new Promise(resolve => setTimeout(() => 
      resolve(new Server()), 2000)); 
    } 

    doSomethingRemote() { 
     this.connection.then(connection => connection.helloWorld()); 
    } 

} 
2

En fin de compte, j'ai essayé une gamme de solutions décorateurs et en utilisant l'objet proxy.

La solution que je suis allé pour était d'utiliser ES7 asynchrone et attendre. Après avoir essayé de comprendre comment cela fonctionne et les pièges, j'ai réussi à le faire fonctionner. Donc, async et await étaient ma solution la plus efficace pour s'assurer que les objets avaient été correctement initialisés. J'ai aussi suivi le conseil de @torazaburo (voir sa réponse ailleurs sur cette page) et j'ai lancé la méthode d'initialisation depuis une usine qui créa et initialisa l'objet.

+0

Avez-vous 'await' dans le constructeur? Comment avez-vous travaillé sur le fait que les constructeurs ne peuvent pas être «asynchrones»? –

+0

@Duke Dougal soin d'élaborer et de nous montrer votre fonction? Serait vraiment utile! :) – mesqueeb