Je veux travailler avec des promesses mais j'ai une API de rappel dans un format comme:
1. Charge DOM ou autre événement ponctuel:
window.onload; // set to callback
...
window.onload = function() {
};
2. Rappel simple:
function request(onChangeHandler) {
...
}
request(function() {
// change happened
...
});
3. Rappel de style de nœud ("nodeback"):
function getStuff(dat, callback) {
...
}
getStuff("dataParam", function(err, data) {
...
})
4. Toute une bibliothèque avec des rappels de style nœud:
API;
API.one(function(err, data) {
API.two(function(err, data2) {
API.three(function(err, data3) {
...
});
});
});
new Promise
ajout entraîne- t-elle des frais généraux importants? Je souhaite encapsuler toutes mes fonctions Noje.js synchrones dans une promesse afin de supprimer tout le code synchrone de mon application Node, mais est-ce la meilleure pratique? En d'autres termes, une fonction qui accepte un argument statique (par exemple une chaîne) et renvoie un résultat calculé, dois-je envelopper cela dans une promesse? ... J'ai lu quelque part que vous ne devriez pas avoir de code synchrone dans Nodejs.Réponses:
Les promesses ont un statut, elles commencent comme en suspens et peuvent se régler pour:
Les fonctions de retour de promesse ne devraient jamais être lancées , elles devraient plutôt renvoyer les rejets. Le fait de quitter une fonction de retour de promesse vous obligera à utiliser à la fois a
} catch {
et a.catch
. Les personnes utilisant des API promises ne s'attendent pas à ce que des promesses soient lancées. Si vous n'êtes pas sûr du fonctionnement des API asynchrones dans JS, veuillez d'abord lire cette réponse .1. Charge DOM ou autre événement ponctuel:
Donc, créer des promesses signifie généralement spécifier quand ils s'installent - cela signifie quand ils passent à la phase remplie ou rejetée pour indiquer que les données sont disponibles (et accessibles avec
.then
).Avec des implémentations de promesses modernes qui prennent en charge le
Promise
constructeur comme les promesses natives d'ES6:Vous utiliseriez alors la promesse résultante comme ceci:
Avec les bibliothèques qui prennent en charge différé (utilisons $ q pour cet exemple ici, mais nous utiliserons également jQuery plus tard):
Ou avec une API comme jQuery, accrocher un événement qui se produit une fois:
2. Rappel simple:
Ces API sont plutôt courantes car bon… les rappels sont courants dans JS. Regardons le cas commun d'avoir
onSuccess
etonFail
:Avec des implémentations de promesses modernes qui prennent en charge le
Promise
constructeur comme les promesses natives d'ES6:Avec les bibliothèques qui prennent en charge différé (utilisons jQuery pour cet exemple ici, mais nous avons également utilisé $ q ci-dessus):
jQuery propose également un
$.Deferred(fn)
formulaire, qui a l'avantage de nous permettre d'écrire une expression qui émule de très près lenew Promise(fn)
formulaire, comme suit:Remarque: Ici, nous exploitons le fait qu'un jQuery différé
resolve
et lesreject
méthodes sont "détachables"; c'est à dire. ils sont liés à l' instance d'un jQuery.Deferred (). Toutes les bibliothèques n'offrent pas cette fonctionnalité.3. Rappel de style de nœud ("nodeback"):
Les rappels de style nœud (nœuds) ont un format particulier où les rappels sont toujours le dernier argument et son premier paramètre est une erreur. Promettons d'abord un manuellement:
À:
Avec les reports, vous pouvez effectuer les opérations suivantes (utilisons Q pour cet exemple, bien que Q supporte désormais la nouvelle syntaxe que vous devriez préférer ):
En général, vous ne devez pas trop promettre des choses manuellement, la plupart des bibliothèques de promesses conçues avec Node à l'esprit ainsi que les promesses natives dans Node 8+ ont une méthode intégrée pour promettre les dos de nœud. Par exemple
4. Toute une bibliothèque avec des rappels de style nœud:
Il n'y a pas de règle d'or ici, vous les promettez un par un. Cependant, certaines implémentations de promesse vous permettent de le faire en bloc, par exemple dans Bluebird, la conversion d'une API nodeback en API de promesse est aussi simple que:
Ou avec des promesses natives dans Node :
Remarques:
.then
gestionnaire, vous n'avez pas besoin de promettre des choses. Le renvoi d'une promesse d'un.then
gestionnaire résoudra ou rejettera la valeur de cette promesse. Lancer d'un.then
gestionnaire est également une bonne pratique et rejettera la promesse - c'est la fameuse promesse de sécurité du lancer.onload
cas réel , vous devez utiliseraddEventListener
plutôt queonX
.la source
resolve()
etreject()
sont écrites pour être réutilisables, je me risque que ma modifier proposée est pertinente car elle offre un exemple jQuery de la forme$.Deferred(fn)
, qui est par ailleurs défaut. Si un seul exemple jQuery est inclus, je suggère qu'il devrait être de cette forme plutôt quevar d = $.Deferred();
etc., car les gens devraient être encouragés à utiliser la$.Deferred(fn)
forme souvent négligée , de plus, dans une réponse comme celle-ci, cela place jQuery plus sur un pied d'égalité avec bibliothèques qui utilisent le modèle de constructeur révélateur .$.Deferred(fn)
, si vous modifiez cela dans au lieu de l'exemple existant dans les 15 prochaines minutes, je suis sûr que je peux essayer de l'approuver à temps :)util.promisify
que Node.js va ajouter à son noyau à partir de RC 8.0.0. Son fonctionnement n'est pas très différent de BluebirdPromise.promisify
, mais a l'avantage de ne pas nécessiter de dépendances supplémentaires, au cas où vous voudriez simplement Promise natif. J'ai écrit un article de blog sur util.promisify pour tous ceux qui veulent en savoir plus sur le sujet.Aujourd'hui, je peux utiliser
Promise
inNode.js
comme une simple méthode Javascript.Un exemple simple et basique pour
Promise
(avec la méthode KISS ):Code API Async Javascript simple :
Promise
Code API Javascript Async:(Je recommande de visiter cette belle source )
Promise
Peut également être utilisé avec togetherasync\await
inES7
pour que le flux de programme attende unfullfiled
résultat comme celui-ci:Une autre utilisation avec le même code en utilisant la
.then()
méthodePromise
peut également être utilisé sur n'importe quelle plate-forme basée sur Node.js commereact-native
.Bonus : une méthode hybride
(la méthode de rappel est supposée avoir deux paramètres comme erreur et résultat)
La méthode ci-dessus peut répondre au résultat pour les utilisations de rappel à l'ancienne et Promise.
J'espère que cela t'aides.
la source
Avant de convertir une fonction en promesse dans Node.JS
Après l'avoir converti
Dans le cas où vous devez gérer plusieurs demandes
la source
Je ne pense pas que la
window.onload
suggestion de @Benjamin fonctionnera tout le temps, car elle ne détecte pas si elle est appelée après le chargement. J'en ai été mordu plusieurs fois. Voici une version qui devrait toujours fonctionner:la source
setTimeout(resolve, 0)
(ousetImmediate
, si elle est disponible) pour s'assurer qu'elle est appelée de manière asynchrone?resolve
synchrone est très bien. Lesthen
gestionnaires de Promise sont garantis par le framework d'être appelés de manière asynchrone , qu'ilsresolve
soient appelés de manière synchrone ou non.Node.js 8.0.0 inclut une nouvelle
util.promisify()
API qui permet aux API de style de rappel Node.js standard d'être encapsulées dans une fonction qui renvoie une promesse. Un exemple d'utilisation deutil.promisify()
est illustré ci-dessous.Voir Prise en charge améliorée des promesses
la source
Dans la version candidate pour Node.js 8.0.0, il y a un nouvel utilitaire,
util.promisify
(j'ai écrit sur util.promisify ), qui encapsule la capacité de promettre n'importe quelle fonction.Elle n'est pas très différente des approches suggérées dans les autres réponses, mais a l'avantage d'être une méthode de base et de ne pas nécessiter de dépendances supplémentaires.
Ensuite, vous avez une
readFile
méthode qui renvoie un natifPromise
.la source
util.promisify
deux fois (en 2014 lorsque cette question a été écrite, et il y a quelques mois - ce que j'ai préconisé en tant que membre principal de Node et c'est la version actuelle que nous avons dans Node). Comme il n'est pas encore accessible au public, je ne l'ai pas encore ajouté à cette réponse. Nous apprécierions profondément les commentaires d'utilisation et de savoir quels sont les pièges afin d'avoir de meilleurs documents pour la sortie :)util.promisify
dans votre article de blog :)util.promisify.custom
symbole, il est possible de remplacer le résultat de util.promisify? Pour être honnête, c'était une erreur intentionnelle, car je ne suis pas encore en mesure de trouver un cas d'utilisation utile. Vous pouvez peut-être me donner quelques informations?fs.exists
ou les API qui ne respectent pas la convention Node - un oiseau bleuPromise.promisify
se tromperait, maisutil.promisify
les ferait bien.Vous pouvez utiliser des promesses natives JavaScript avec Node JS.
Lien de code My Cloud 9: https://ide.c9.io/adx2803/native-promises-in-node
la source
Avec le vieux javaScript vanilla, voici une solution pour promettre un rappel api.
la source
La bibliothèque Q de kriskowal comprend des fonctions de rappel à la promesse. Une méthode comme celle-ci:
peut être converti avec Q.ninvoke
la source
Q.denodeify
. Faut-il mettre l'accent sur les aides de bibliothèque?Lorsque vous avez quelques fonctions qui prennent un rappel et que vous souhaitez qu'elles renvoient une promesse, vous pouvez utiliser cette fonction pour effectuer la conversion.
la source
Sous le nœud v7.6 + qui a intégré des promesses et asynchrones:
Comment utiliser:
la source
Dans Node.js 8, vous pouvez promettre des méthodes d'objet à la volée en utilisant ce module npm:
https://www.npmjs.com/package/doasync
Il utilise util.promisify et Proxies pour que vos objets restent inchangés. La mémorisation se fait également avec l'utilisation de WeakMaps). Voici quelques exemples:
Avec des objets:
Avec des fonctions:
Vous pouvez même utiliser natif
call
etapply
pour lier un certain contexte:la source
Vous pouvez utiliser Promise native dans ES6, par exemple pour traiter setTimeout:
Dans cet exemple, la Promesse n'a aucune raison d'échouer, elle
reject()
n'est donc jamais appelée.la source
La fonction de style de rappel est toujours comme ça (presque toutes les fonctions dans node.js sont ce style):
Ce style a la même caractéristique:
la fonction de rappel est passée par le dernier argument.
la fonction de rappel accepte toujours l'objet d'erreur comme premier argument.
Donc, vous pouvez écrire une fonction pour convertir une fonction avec ce style comme ceci:
Pour un exemple plus concis, ci-dessus utilisé ramda.js. Ramda.js est une excellente bibliothèque pour la programmation fonctionnelle. Dans le code ci-dessus, nous avons utilisé l' appliquer (comme javascript
function.prototype.apply
) et l'ajouter (comme javascriptfunction.prototype.push
). Donc, nous pourrions convertir la fonction de style de rappel en fonction de style de promesse maintenant:Promouvoir et fonction checkErr appartient à la bibliothèque berserk , c'est une fourchette de bibliothèque de programmation fonctionnelle par ramda.js (créée par moi).
J'espère que cette réponse vous sera utile.
la source
Vous pouvez faire quelque chose comme ça
Ensuite, utilisez-le
la source
es6-promisify
convertit les fonctions basées sur le rappel en fonctions basées sur Promise.Réf: https://www.npmjs.com/package/es6-promisify
la source
Ma version promis d'une
callback
fonction est laP
fonction:La
P
fonction nécessite que la signature de rappel soitcallback(error,result)
.la source
util.promisify(fn)
(err, value) => ...
ou vous devez en définir une personnalisée (voir Fonctions promises personnalisées). Merci bon catcha.var P = function (fn, ...args) { return new Promise((resolve, reject) => fn.call(this, ...args, (error, result) => error ? reject(error) : resolve(result))); };
ferait la même chose que la vôtre et c'est beaucoup plus simple.Vous trouverez ci-dessous l'implémentation de la façon dont une fonction (API de rappel) peut être convertie en promesse.
la source
C'est comme 5 ans de retard, mais je voulais poster ici ma version promesify qui prend les fonctions de l'API de rappel et les transforme en promesses
Jetez un œil à cette version très simple ici: https://gist.github.com/jdtorregrosas/aeee96dd07558a5d18db1ff02f31e21a
la source