C'est une mauvaise pratique d'avoir un constructeur de retour de la fonction une Promesse?
Je suis en train de créer un constructeur pour une plate-forme de blogs et il a de nombreuses opérations asynchrones passe à l'intérieur. Celles-ci vont de l'accaparement des postes à partir de répertoires, l'analyse de leur, de les envoyer par le biais de moteurs de template, etc.
Donc ma question est, ne serait-il pas judicieux d'avoir mon constructeur de retour de la fonction une promesse à la place d'un objet de la fonction qu'ils ont appelé new
contre.
Par exemple:
var engine = new Engine({path: '/path/to/posts'}).then(function (eng) {
//allow user to interact with the newly created engine object inside 'then'
engine.showPostsOnOnePage();
});
Maintenant, l'utilisateur peut également pas fournir un supplément de Promesse de maillon de chaîne:
var engine = new Engine({path: '/path/to/posts'});
//ERROR
//engine will not be available as an Engine object here
Cela pourrait poser un problème que l'utilisateur peut être confondu pourquoi engine
n'est pas disponible après la construction.
La raison de l'utilisation d'une Promesse dans le constructeur de sens. Je veux que le blog à fonctionner après la phase de construction. Cependant, il semble comme une odeur presque de ne pas avoir accès à l'objet immédiatement après l'appel de new
.
J'ai débattu à l'aide de quelque chose le long des lignes de engine.start().then()
ou engine.init()
qui permettrait le retour de la Promesse à la place. Mais aussi celles qui semblent malodorante.
Edit: C'est dans un Node.js projet.
- Est la création de l'objet de l'opération asynchrone ou à l'acquisition de ses ressources vraiment l'opération asynchrone? Je pense que vous n'aurez pas ce problème si vous avez utilisé DI
- La conception la plus courante modèle que j'ai vu pour ce type de question est simplement de créer votre objet shell dans le constructeur et ensuite faire toutes les async trucs dans un
.init()
méthode qui peut ensuite retourner la promesse. Alors vous séparer de données de l'instance de l'objet et de la construction de l'objet de l'opération d'initialisation asynchrone. Le même problème se pose lorsque vous avez toutes sortes d'erreurs (lesquelles l'appelant veut traiter différemment) qui peuvent se produire lors de l'initialisation de l'objet. Beaucoup mieux de retourner l'objet dans le constructeur et ensuite utiliser.init()
pour renvoyer d'autres choses. - Je suis totalement d'accord avec jfriend00. Il est préférable d'utiliser une méthode init à faire une promesse!
Vous devez vous connecter pour publier un commentaire.
Oui, c'est une mauvaise pratique. Un constructeur doit retourner une instance de sa classe, rien d'autre. Il serait gâcher le
new
de l'opérateur et à l'héritage autrement.En outre, un constructeur ne devrait créer et initialiser une nouvelle instance. Il devrait mettre en place des structures de données et toutes les instance de propriétés spécifiques, mais pas exécuter toutes les tâches. Il devrait être un fonction pure sans effets secondaires, si possible, avec tous les avantages qu'il possède.
Qui devrait aller dans une méthode de la classe. Vous souhaitez muter état global? Puis appeler cette procédure explicitement, non pas comme un effet secondaire de la génération d'un objet. Cet appel peut aller à droite après l'instanciation:
Si cette tâche est asynchrone, vous pouvez maintenant retourner facilement une promesse pour ses résultats à partir de la méthode, facilement attendre qu'il est fini.
Je voudrais cependant de ne pas recommander ce modèle lorsque la méthode (de manière asynchrone) mutation de l'instance et d'autres méthodes dépendent que, comme cela conduirait à eux d'être obligé d'attendre (devenir async même si elles sont en fait synchrone) et que vous souhaitez avoir rapidement de certains internes de gestion de file d'attente en cours. Ne pas coder les instances d'exister, mais être réellement inutilisable.
Demandez-vous: avez-vous réellement besoin de l'instance sans les données? Pourriez-vous l'utiliser en quelque sorte?
Si la réponse est Pas, alors vous ne devriez pas le créer avant d'avoir les données. Rendre les données ifself un paramètre à votre constructeur, au lieu de dire le constructeur pour récupérer les données (ou de passer une promesse pour les données).
Ensuite, utilisez une méthode statique pour charger les données, à partir de laquelle vous retournez une promesse. Puis la chaîne d'un appel qui encapsule les données dans une nouvelle instance sur que:
Cela permet beaucoup plus de flexibilité dans les moyens d'acquérir les données, et simplifie le constructeur de beaucoup. De même, vous pouvez écrire statique d'usine des fonctions qui renvoient des promesses pour
Engine
instances:(new Engine) instanceof Engine
est faux, c'est vraiment inattendu. De même, lorsque vous essayez d'hériter de cette classe,super(…)
initialisethis
avec une promesse non une instance du moteur - un gâchis. Ne pasreturn
de constructeurs.{path: '/path/to/posts'}
c'est statiquement déclaré, que si vous vous déclarez le chemin d'accès dans le constructeur, donc la seule façon de l'obtenir est de l'instancier.load
fonction? Vous pourriez voulez poser une nouvelle question de partager votre code et être précis sur les objectifs que vous avez et les restrictions que vous devez affronter.static load
méthode, pourrait aussi utiliser la nouvelleawait
si vous déclarez unestatic async
donc, commelet data = await Engine.load
puis il suffit de passer dans le constructeur.J'ai rencontré le même problème et est venu avec cette solution simple.
Au lieu de retourner une Promesse du constructeur, le mettre dans
this.initialization
propriété, comme ceci:Ensuite, enveloppez chaque méthode dans un rappel qui s'exécute après l'initialisation, comme ça:
À quoi ça ressemble de l'API point de vue du consommateur:
Cela fonctionne parce que vous pouvez enregistrer plusieurs rappels à une promesse, et ils courent après il se résout ou, si elle est déjà résolue, au moment de la fixation de la fonction de rappel.
C'est de cette façon mongoskin fonctionne, sauf qu'il n'en utilisent pas des promesses.
Edit: Depuis que j'ai écrit cette réponse, je suis tombé en amour avec ES6/7 syntaxe il y a donc un autre exemple d'utilisation que. Vous pouvez l'utiliser aujourd'hui avec babel.
Modifier: Vous pouvez utiliser ce modèle de manière native avec nœud 7 et
--harmony
drapeau!Pour éviter la séparation des préoccupations, utiliser une factory pour créer l'objet.
Promise
constructeur antipattern!La valeur de retour du constructeur remplace l'objet que l'opérateur new juste produit, afin de retourner une promesse n'est pas une bonne idée. Auparavant, une valeur de retour explicite du constructeur a été utilisé pour le pattern singleton.
La meilleure façon en ECMAScript 2017 est d'utiliser une des méthodes statiques: vous avez un processus, qui est la numerality de statique.
La méthode à exécuter sur le nouvel objet après le constructeur peut être connu seulement à la classe elle-même. Pour encapsuler ce à l'intérieur de la classe, vous pouvez utiliser le processus.nextTick ou d'une Promesse.résoudre, le report de la poursuite de l'exécution en permettant aux auditeurs d'être ajoutés et d'autres choses dans le Processus.lancement, l'invocateur du constructeur.
Depuis presque tout le code s'exécute à l'intérieur d'une Promesse, des erreurs se retrouvent dans le Processus.fatale
Cette idée de base peut être modifié pour s'adapter spécifiques encapsulation besoins.