Mongoose: Possibilité de spécifier quelle bibliothèque ES6 promet la mangouste utilisée

Créé le 17 févr. 2015  ·  45Commentaires  ·  Source: Automattic/mongoose

Voir discussion sur #1699

Commentaire le plus utile

Oui, require('mongoose').Promise = global.Promise fera en sorte que la mangouste utilise les promesses natives. Vous devriez cependant pouvoir utiliser n'importe quel constructeur de promesses ES6, mais pour le moment, nous ne testons qu'avec natif, bluebird et Q

Tous les 45 commentaires

J'ai vraiment hâte de pouvoir utiliser Promise.all(), pour faire quelque chose une fois que tout le travail de base de données a été effectué.

:+1:

Une chose qui n'était pas très claire sur https://github.com/LearnBoost/mongoose/issues/1699 est quelle implémentation sera la valeur par défaut.

Etant donné qu'il ne s'agit pas d'une version rétrograde, mpromise devra être la valeur par défaut, mais vous pourrez passer outre.

+1

:+1:

Y a-t-il une branche où cela est piraté? Je ne supporte pas le flux de gestion des erreurs avec mpromise et je suis sur le point d'ouvrir la source pour voir ce que cela prendrait.

promesse :

  query.exec()
    .then(function(ou) {
      if(!ou) {
        return next(new errors.http.NotFound('The specified OU was either not found, or your credentials lack the required permissions to view it.'));
      }

      res.send(ou);
    }, next)
    .end(next);

Je dois gérer le rejet et y mettre end . Sans end , les exceptions (par exemple, j'ai mal orthographié la classe NotFound) sont silencieusement avalées et n'expriment que des blocages.

oiseau bleu:

  query.exec()
    .then(function(ou) {
      if(!ou) {
        return next(new errors.http.NotFound('The specified OU was either not found, or your credentials lack the required permissions to view it.'));
      }

      res.send(ou);
    })
    .catch(next);

Faire promisifyAll(require('mongoose')) semble toujours fonctionner avec Mongoose 4 jusqu'à présent. Les tests de régression qui couvrent cela seraient-ils trop ciblés ?

Pas pour le moment. La plupart du travail aura lieu dans le module kareem selon # 2754 et vkarpov15/kareem # 2, car cela nous permettra de faire d'une pierre deux coups et de supprimer le non-sens vraiment désordonné qui a été écrit pour faire des crochets et des promesses travailler ensemble. N'hésitez pas à essayer, je suis ouvert aux relations publiques.

Mais pourquoi devrions-nous garder le support pour d'autres bibliothèques de promesses ? La spécification ES6 Promises est désormais solide comme le roc et là pour rester. Ne pouvons-nous pas simplement utiliser des promesses ES6 pures, avec un polyfill chargé lorsqu'elles ne sont pas disponibles dans les anciennes versions de node ?

Si c'est le cas, je peux essayer.

Le fait est que vous pourrez utiliser n'importe quelle bibliothèque de promesses compatible ES6 que vous aimez. Beaucoup de gens sont encore fortement investis dans bluebird, when, q, rsvp, etc. etc. et chacune de ces bibliothèques a ses propres bizarreries particulières qu'un polyfill générique ne capturera pas.

Je suis ouvert aux suggestions alternatives - je n'aime pas particulièrement ou n'utilise pas les promesses, cette fonctionnalité est motivée par le fait qu'il y a une montagne de problèmes impliquant des personnes demandant "support bluebird feature X in mpromise" ou "support rsvp.js natif " et laisser les gens apporter leur propre bibliothèque de promesses à la fête est le moyen le plus simple de résoudre ces problèmes.

Je vois ce que tu veux dire. Je suis un grand utilisateur et un partisan des promesses. Je pense que cela devrait être envisagé pour faire respecter la norme.
Les promesses A + ont été choisies comme référence pour l'ES6. J'ai suggéré le polyfill pour assurer la prise en charge des versions de nœuds incompatibles avec ES6 (par exemple, https://github.com/jakearchibald/es6-promise).

Il devrait être entre les mains de l'autre bibliothèque de promesses pour être compatible et mixable avec les promesses ES6.

ÉDITER:
Et il n'y aurait pas de rupture dans l'API actuelle ou ai-je raté quelque chose ?

La spécification Promises/A+ est très différente de la spécification des promesses ES6, qui est à son tour différente des bibliothèques de promesses que j'ai énumérées dans les commentaires précédents. Bien qu'il serait bon pour moi que la myriade de bibliothèques de promesses soient toutes consolidées dans ES6, je doute que cela se produise un jour, car la beauté de l'open source est que certaines personnes qui aiment les promesses voudront des fonctionnalités supplémentaires et écriront leurs propres promesses bibliothèques.

Pas de changement de rupture pour l'API actuelle, ce que je pense est une façon de dire mongoose.set('Promise', require('bluebird')); ou quelque chose comme ça, donc ce serait un opt-in et mpromise serait la valeur par défaut.

Ah d'accord, désolé pour cette erreur.
J'ai jeté un coup d'œil à l'implémentation actuelle et à l'autre bibliothèque de promesses.

Je pense que je peux faire quelque chose comme ça:

mongoose.set('Promise', Promise);

mongoose.set('Promise', require('bluebird'));

mongoose.set('Promise', require('q').defer());

mongoose.set('Promise', require('when').defer());

// and so on...

Donc, fondamentalement, vous devriez exposer à Mongoose votre objet promesse de choix qui a les méthodes resolve et reject .

Serait-ce ce que vous aviez en tête ? Si c'est le cas, je travaillerai sur une pull request.

ÉDITER:
C'est extrêmement idiot d'écrire mongoose.set('Promise', Promise); . Je pense que ES6 devrait être la valeur par défaut, avec la possibilité d'utiliser la bibliothèque de votre choix (et mpromise chaque fois que les promesses ES6 ne sont pas disponibles).

Bien sûr, j'apprécierais votre aide. Le plus délicat serait 1) de le faire fonctionner avec des hooks - voir vkarpov15/kareem#2, et 2) de le rendre rétrocompatible avec mpromise.

Aussi, re: Q, nous utiliserons require('q').Promise car c'est la syntaxe Q la plus proche de la spécification ES6

Merci pour votre contribution, je vais y travailler. Préférez-vous une pull request compétitive ou un PR en cours ?

Terminé c'est mieux, mais j'aurai invariablement quelques suggestions. Faites-moi savoir si vous êtes coincé

+1 pour cette fonctionnalité. je voudrais utiliser avec bluebird

Désolé d'être drastique - mais une approche alternative serait de déprécier complètement le support des promesses. Cela ferait taire quiconque utilisant des promesses demandant le soutien d'autres bibliothèques.
Les personnes utilisant de puissantes bibliothèques de promesses comme bluebird peuvent continuer à l'utiliser de toute façon puisque vous exposez une API de rappel et que bluebird peut l'envelopper trivialement à un coût nul - en fait, il y a de fortes chances que puisque vous ne connaissez pas ou n'utilisez pas de promesses (comme vous l'avez dit), il y a des chances il sera de toute façon plus lent et plus sujet aux erreurs de les prendre en charge manuellement.

@benjamingr 100% pas d'accord. Désormais, avec la fusion d'iojs et de NodeJs dans Node 3.0, les promesses et les générateurs ES6 seront pris en charge.

Abandonner le soutien serait un énorme pas en arrière.

Autrement dit, Promise.promisifyAll(require("mongoose")) crée un wrapper rapide (plus rapide que toute tentative manuelle probable) pour Mongoose qui est conforme aux normes et entoure toute l'API sans que vous ayez à faire quoi que ce soit à ce sujet. En fait, vous pouvez faire Promise.promisifyAll sur l'objet exports vous-même et exposer les promesses bluebird et la méthode des doubles promesses (save - saveAsync) gratuitement, puis dire que vous exposez une interface de promesse bluebird sans avoir à faire de travail réel.

Ainsi, alors que j'utilise moi-même les promesses de bluebird - je pense que tout cela peut être corrigé par une section dans la documentation plutôt que de compliquer votre code en codant sur deux interfaces.

@albertorestifo sauf que rien ne sera réellement abandonné. Je suis très conscient de ce que sont les promesses (plus de 1500 points et 500 réponses en débordement de pile :P) et je suis même responsable de certaines parties de leur fonctionnement dans io.js (comme https://github.com/ nodejs/io.js/issues/256).

Cela ne change rien au fait que je crois que puisque @ vkarpov15 n'utilise pas de promesses, il ne devrait pas avoir à les prendre en charge dans sa bibliothèque _d'autant plus que cela n'apporte aucun avantage par rapport à l'utilisation de promesses de toute façon_. Vous pouvez utiliser les promesses avec mangouste aussi facilement même si elles ne les fournissent pas - la prise en charge de la mise en œuvre de mangouste en interne est plus à maintenir, probablement plus lente et plus sujette aux erreurs. @ vkarpov15 peut continuer à travailler sur l'API de rappel et promettre que les utilisateurs peuvent envelopper Mongoose avec des promesses avec une seule doublure facile de toute façon.

@benjamingr qui suppose que l'on utilise une bibliothèque Promise externe. Je m'en tiens à celui des spécifications, et vous le savez très bien, il n'a pas d'emballage.

Je vois votre point. Soutenir les deux crée un énorme gâchis. Personnellement, je méprise les rappels, donc je les laisserais tomber à la place. Il devrait peut-être y avoir deux référentiels distincts, l'un utilisant des générateurs et des promesses, l'autre utilisant des rappels. Les deux conserveraient la même structure et l'API aussi proche que possible.

@benjamingr qui suppose que l'on utilise une bibliothèque Promise externe. Je m'en tiens à celui des spécifications, et vous le savez très bien, il n'a pas d'emballage.

Si vous choisissez d'utiliser une implémentation lente, plus difficile à déboguer et moins riche en fonctionnalités, c'est bien sûr votre choix :P mais comment cela est-il lié au wrapper ? Il est parfaitement facile d'écrire un wrapper similaire au promisifyAll en utilisant des promesses natives*.

Si vous voulez une version promise - activée de Mongoose en tant que package séparé, voici comment vous pouvez le faire :

  • Étape 1, ouvrez votre éditeur préféré ou simplement un éditeur avec lequel vous êtes plutôt d'accord.
  • Étape 2, tapez module.exports = require("bluebird").promisifyAll(require("mongoose"))
  • Étape 3, créez le fichier package.json approprié, publiez sur npm
  • Étape 4, des dizaines de milliers de téléchargements.

Maintenant, je sais ce que vous pensez "cela n'utilise pas de promesses natives", eh bien vous pouvez toujours supprimer toutes les méthodes sauf then et catch du prototype de promesse et all et race partir de Promise et se retrouvent avec la même API - ou vous pouvez simplement dire aux gens que vous exportez des promesses natives - ils ne le sauront pas puisqu'il ne s'agit que de deux implémentations Promises/A+, Je promets ;)

(* l'écrire rapidement est plus difficile au niveau utilisateur car il n'y a pas de moyen rapide de créer des promesses pour le moment, c'est pourquoi io.js exportera probablement une fonction de promesse elle-même éventuellement - cela dit en prenant un constructeur de promesses, vous le forcez à être lent quand même).

C'est certainement une alternative décente. Je voudrais cependant tenir mes promesses en interne, car, que cela plaise ou non, c'est ainsi que les utilisateurs vont utiliser la mangouste, donc nous pourrions aussi bien avoir une couverture de test solide pour cela, afin que nous puissions pointer et dire "c'est comme ça vous utilisez la bibliothèque promise X avec mangouste". L'inconvénient lorsque vous déconnectez les choses dans des modules séparés est qu'il est difficile de dire "ok cette version de mangoose-promises ne fonctionne qu'avec mangouste 3.8, celle-ci fonctionne avec mangouste>= 4.1" et il est difficile pour mongoose d'éviter de casser un emballage de promesses global .

C'est certainement une alternative décente. J'aimerais cependant tenir nos promesses en interne, car, que cela plaise ou non, c'est ainsi que les utilisateurs vont utiliser la mangouste, donc nous pourrions aussi bien avoir une couverture de test solide pour cela,

Pourquoi voudriez-vous / auriez-vous besoin d'une couverture de test pour cela ? Il ne sert à rien de tester les promesses elles-mêmes dans votre code - les bibliothèques ont déjà des tests - c'est comme tester le module http lorsque vous l'utilisez.

et il est difficile pour la mangouste d'éviter de briser un emballage de promesses primordial.

Bluebird fait quelque chose de très simple - il trouve des prototypes et leur ajoute ensuite des méthodes avec le suffixe Async - c'est très simple et cela fonctionne bien dans la pratique - c'est une doublure avec la plupart des bibliothèques, y compris Mongoose et il ne s'est pas cassé même une fois pour moi l'année dernière.

Je ne sais pas pourquoi vous voudriez conserver beaucoup de code d'assemblage potentiellement sujet aux erreurs, le fait de devoir prendre en charge manuellement deux API avec leurs cas extrêmes semble demander beaucoup de travail et vous pouvez casser des choses au fur et à mesure - vous pouvez "empruntez" le code promisifyAll de bluebird et adaptez-le pour qu'il fonctionne avec d'autres bibliothèques promises (c'est open source après tout), mais je ne le ferais certainement pas manuellement.

"ok cette version de mangoose-promises ne fonctionne qu'avec mangouste 3.8, celle-ci fonctionne avec mangouste>= 4.1" et il est difficile pour mongoose d'éviter de casser un emballage de promesses global.

Eh bien, pourriez-vous me donner un exemple d'un changement radical qui devrait se produire si la promesse est automatique ?

1) J'aimerais tester les choses de la façon dont les utilisateurs les utilisent.

2) J'aimerais être paresseux et l'éviter, mais si je comprends bien, la plupart des autres bibliothèques de promesses n'ont pas d'équivalent promisifyAll. Je suppose que c'est pourquoi "support Xpromise feature Y" est la demande de fonctionnalité de mangouste la plus populaire. De plus, nous n'avons pas l'intention de réécrire la promesse de Bluebird, il suffit de faire en sorte que les fonctions de mangouste renvoient une promesse nativement.

3) Dépend de la mise en œuvre de la promesse et de la façon dont vous l'utilisez :)

1) J'aimerais tester les choses de la façon dont les utilisateurs les utilisent.

Qu'entendez-vous par tester la façon dont les utilisateurs les utilisent ? Pouvez-vous me montrer une analogie pour les rappels ?

2) J'aimerais être paresseux et l'éviter, mais si je comprends bien, la plupart des autres bibliothèques de promesses n'ont pas d'équivalent promisifyAll. Je suppose que c'est pourquoi "support Xpromise feature Y" est la demande de fonctionnalité de mangouste la plus populaire. De plus, nous n'avons pas l'intention de réécrire la promesse de Bluebird, il suffit de faire en sorte que les fonctions de mangouste renvoient une promesse nativement.

Vous n'avez pas à réécrire, vous pouvez le prendre - ce n'est pas générique car une implémentation générique serait plus lente.

Ce n'est pas non plus de la paresse de ne pas implémenter manuellement une fonctionnalité largement disponible. NodeJS est-il paresseux pour ne pas mettre express dans le noyau ? TC39 est-il paresseux pour ne pas mettre de soulignement dans le noyau ? En vous en tenant à une convention (rappels), vous donnez aux utilisateurs la possibilité d'utiliser la primitive de concurrence de leur choix.

3) Dépend de la mise en œuvre de la promesse et de la façon dont vous l'utilisez :)

Eh bien, la promesse de bluebird, ou Q ou When - ils varient dans leur mise en œuvre mais ils font tous la même chose - alors choisissez-en un que vous aimez. Je me demandais juste comment ça se cassait.

Il y a une chose qui me manque dans cette discussion ici:

Si mongoose renvoie une promesse standard (par standard, c'est-à-dire l'implémentation native ES6), ne devrait-elle pas être compatible avec n'importe quelle bibliothèque Promise compatible ES6 ? Je peux faire Promise.all([model.query().exec(), ...]) très bien, ainsi que le bluebird, q, lorsqu'il est équivalent.

Alors, pourquoi ne pas renvoyer les rappels et les promesses standard (comme c'est le cas maintenant, mais en "se débarrassant" de mpromise) et laisser l'utilisateur utiliser sa bibliothèque de promesses préférée ? Ou est-ce que je manque quelque chose ici?

@albertorestifo eh bien, les promesses natives sont lentes pour le moment et cela prendra du temps, potentiellement des années avant qu'elles n'atteignent la parité avec les bibliothèques userland - donc principalement cela.

@benjamingr vous faites quelques bons points. Le principal objectif des promesses de mongoose est de vous permettre d'utiliser yield avec des opérations asynchrones de mongoose sans aucune autre bibliothèque, c'est pourquoi nous tenons nos promesses dans un avenir prévisible. IMO c'est quelque chose qui devrait vraiment faire partie du noyau de la mangouste à l'avenir.

Est-ce que Q ou When ont une capacité de promesse ?

Est-ce que Q ou When ont une capacité de promesse ?

Oui, pratiquement toutes les bibliothèques de promesses répandues que je connais offrent une sorte de promesse :

Voici quand : https://github.com/cujojs/when/blob/master/docs/api.md#nodeliftall
Voici Q : https://github.com/kriskowal/q/wiki/API-Reference#qnfbindnodefunc -args

Les promesses natives ne l'ont pas encore, mais c'est quelque chose sur lequel on travaille - une fois qu'un chemin rapide pour créer des promesses (c'est-à-dire - pas le constructeur de promesses) existe, NodeJS le prendra probablement en charge dans le noyau pour les promesses natives (puisqu'il peut ' pas être fait _rapidement_ en userland).

Le point principal des promesses de mongoose est de vous permettre d'utiliser le rendement avec les opérations asynchrones de mongoose sans aucune autre bibliothèque

Vous avez besoin d'une bibliothèque pour utiliser yield de manière significative avec des promesses de toute façon. Si vous pouvez écrire vous-même les 9 LoC qui pompent un générateur en tant que fonction asynchrone, vous pouvez certainement écrire promisify - et si vous êtes comme la plupart des utilisateurs, vous utilisez de toute façon une bibliothèque pour cela.

Je vois vraiment le besoin/le besoin d'autoriser les promesses dans Mongoose, c'est la voie à suivre et la manière dont le langage fonctionne maintenant, mais je pense honnêtement que le faire manuellement, méthode par méthode, sera douloureux. Il peut être avantageux de démontrer simplement comment cela se fait en utilisant des bibliothèques dans une section "utilisation avec des promesses" ou "utilisation avec des générateurs" dans la documentation.

Le fait est que nous l'avons déjà fait méthode par méthode, nous avons juste besoin de modifier le wrapper de promesse interne. Quoi qu'il en soit, nous ne pouvons pas tout à fait supprimer les promesses du noyau avant la version 5.0. Je suis favorable à l'idée de le déprécier, @benjamingr fait de bons arguments que je vais devoir examiner de près, mais je pense que la prochaine étape serait de toute façon # 2688.

Vous avez évidemment plus d'expérience avec Mongoose et plus important encore, ce sont les utilisateurs - donc je comprends ce choix. Merci beaucoup de m'avoir écouté.

J'ai tapé "son" mais mon iPhone avait l'impression qu'il devrait le corriger automatiquement en "c'est" et GitHub a estimé que l'édition de commentaires n'était pas un cas d'utilisation intéressant. Désolé pour le double-commentaire-spam :)

Vous pouvez modifier les commentaires sur le site Web si vous cliquez sur le crayon en haut à droite de votre commentaire.

Je suis toujours ouvert à un bon débat chaleureux, surtout celui qui m'apprend quelque chose de nouveau : bières : je peux vous envoyer un ping plus tard pour en discuter davantage :)

L'avenir appartient aux promesses indigènes, semble-t-il. Mongoose est un standard de l'industrie pour les opérations mongo, il est tout à fait valable qu'il s'appuie également sur des promesses standard.

Les promesses standard mûriront inévitablement et deviendront plus répandues que n'importe quel cadre. Un humble +1 pour les utiliser.

@iliakan peut-être dans le futur. Je ne m'attendrais pas à ce que les promesses natives deviennent la "norme" avant la mi-2016 au plus tôt, les diverses bibliothèques de promesses fragmentées sont trop profondément ancrées et ont trop de bizarreries subtiles. Quoi qu'il en soit, la mangouste ne peut pas passer au "natif par défaut" sans un changement massif en arrière.

@ vkarpov15 bien sûr que je comprends.

Ce qui pourrait être bénéfique en attendant - une simple page qui décrit les incompatibilités majeures entre mpromise et native promises. Au moins des choses que vous ne devriez pas essayer avec mpromise ;)

Est-ce que je comprends bien qu'il n'y a pas catch en ce moment, et c'est toutes les limitations ?

Aucune idée, je n'ai pas vraiment approfondi l'API ES6. mpromise implémente Promises/A+ et rien d'autre, ce qui signifie pas de .catch(), pas de longues traces de pile, etc. etc. En gros, tout ce qui n'est pas .then() est en dehors de la portée de l'implémentation de mpromise.

De manière générale, quelque chose qui implémente Promises/A+ implémente également les promesses ES6 d'un point de vue de haut niveau, mais l'inverse n'est pas vrai. Promises/A+ est très spécifique sur les détails d'implémentation de bas niveau, par exemple, bluebird n'obéit pas exactement à Promises/A+, et je ne suis pas sûr des autres bibliothèques de promesses courantes, mais je suis sûr qu'elles n'obéissent pas à la spécification dans leurs propres manières uniques. C'est ce qui va rendre cela particulièrement délicat.

Vous voulez dire, pouvez-vous maintenant utiliser Bluebird et les promesses natives ?

Oui, require('mongoose').Promise = global.Promise fera en sorte que la mangouste utilise les promesses natives. Vous devriez cependant pouvoir utiliser n'importe quel constructeur de promesses ES6, mais pour le moment, nous ne testons qu'avec natif, bluebird et Q

@vkarpov15 C'est génial ! Merci beaucoup!

@vkarpov15 Merci beaucoup ! Bon travail!

Ouais absolument. C'est vraiment cool! :)

@ vkarpov15 C'est vraiment sympa

Cette page vous a été utile?
0 / 5 - 0 notes