J'ai mis à jour un code Node.js plus ancien. Au cours du processus, je conçois de nouveaux modules pour travailler avec l'ancien code. Je constate que maintenant, contrairement à la première fois que j'ai écrit ceci, je me fie davantage à l'utilisation des promesses ES6 qu'à des rappels. Alors maintenant, j'ai ce mélange de fonctions qui renvoient des promesses et d'autres qui prennent des rappels - ce qui est fastidieux. Je pense que finalement, il devrait être remanié pour utiliser les promesses. Mais avant que cela soit fait ...
Quelles sont les situations où les promesses sont préférées et où les rappels sont préférés?
Existe-t-il un type de situation qu'un rappel peut gérer mieux qu'une promesse et inversement?
D'après ce que j'ai vu jusqu'à présent, je ne vois vraiment aucune raison d'utiliser des rappels au lieu de promesses. Est-ce vrai?
Tout d'abord, vous ne voulez pratiquement jamais écrire du code combinant des rappels et des promesses d'opérations asynchrones. Si vous passez aux promesses ou si vous présentez des promesses, vous voudrez probablement reformuler les rappels de cette même section de code en promesses. Pour les types d'opérations appropriés, les avantages des promesses par rapport aux rappels en clair présentent tellement d'avantages que les efforts de conversion valent vraiment la peine d'être convertis lorsque vous travaillez déjà dans un domaine de code.
Les promesses sont bonnes pour:
pending
, fulfilled
et rejected
et où l'état passe de pending => fulfilled
ou de pending => rejected
ne peut pas être modifié (une seule transition à sens unique).Les rappels en clair sont bons pour des choses que les promesses ne peuvent pas faire:
Array.prototype.map()
)Et, j'ajouterais aussi EventEmitter
au mélange.
EventEmitters sont parfaits pour:
Notes sur la conversion du code de rappel brut en Promises
Si vos rappels respectent la convention d'appel du nœud avec le rappel passé en tant que dernier argument et appelé comme suit: callback(err, result)
, vous encapsulerez automatiquement la fonction parent dans une promesse avec util.promisify()
dans node.js ou si vous utilisez la bibliothèque bibliothèque de promesses Bluebird , avec Promise.promisify()
.
Avec Bluebird, vous pouvez même promisifier un module entier (qui utilise des rappels asynchrones dans la convention d’appel de node.js) à la fois, par exemple:
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
fs.writeFileAsync("file.txt", data).then(() => {
// done here
}).catch(err => {
// error here
});
Dans node.js version 8+
Il existe maintenant util.promisify()
qui convertira une fonction asynchrone utilisant la convention d’appel asynchrone node.js en une fonction renvoyant une promesse.
Exemple de la doc:
const util = require('util');
const fs = require('fs');
const stat = util.promisify(fs.stat);
// usage of promisified function
stat('.').then((stats) => {
// Do something with `stats`
}).catch((error) => {
// Handle the error.
});
Ils existent tous les deux pour résoudre le même problème, gérer le résultat d’une fonction asynchrone.
Les rappels ont tendance à être plus détaillés et la coordination simultanée de plusieurs demandes asynchrones peut conduire à callback hell si vous ne modulez pas activement vos fonctions. La gestion et le suivi des erreurs ont tendance à être moins simples et même source de confusion, car il peut y avoir de nombreux objets d'erreur qui retournent tous à une seule erreur plus loin dans la pile d'appels. Les erreurs doivent également être renvoyées à l'appelant d'origine, ce qui peut également entraîner des problèmes de tête lors de la détermination de l'emplacement de l'erreur d'origine si des fonctions anonymes ont été utilisées dans la chaîne de rappel. L'un des avantages des rappels réside dans le fait qu'ils sont simplement d'anciennes fonctions et ne nécessitent aucune compréhension supplémentaire, à part la connaissance du fonctionnement d'une opération asynchrone.
Les promesses sont plus courantes car elles nécessitent moins de code, sont plus lisibles car elles sont écrites comme des fonctions synchrones, ont un seul canal d’erreur, peuvent gérer les erreurs renvoyées et/ util.promisify()
ajouté dans la dernière version de Node.js, peut convertir erreur-premiers rappels en promesses. Il y a aussi async/await
qui est fait son chemin dans Node.js maintenant aussi, et ils ont aussi une interface avec Promises.
Ceci est totalement basé sur l'opinion, donc c'est vraiment ce avec quoi vous êtes le plus à l'aise, mais Promises et async/await
représentent l'évolution du rappel et améliorent l'expérience de développement asynchrone. Ce n'est pas une comparaison exhaustive, loin de là, mais plutôt un regard approfondi sur les rappels et les promesses.