web-dev-qa-db-fra.com

devrais-je utiliser `return` in Promise?

function saveToTheDb(value) {  
  return new Promise(function(resolve, reject) {
    db.values.insert(value, function(err, user) { // remember error first ;)
      if (err) {
        return reject(err); // don't forget to return here
      }
      resolve(user);
    })
  }
}

Voici le code que je vois depuis ici . Je suis confus à propos du mot clé return.

Pour resolve(user);, ai-je besoin de return?

Pour reject(user);, ai-je besoin de return?

16
BlackMamba

Il n'est pas nécessaire d'utiliser une instruction return dans un callback new Promise(). Le constructeur Promise n'attend aucune sorte de valeur de retour du rappel.

Ainsi, la raison d'utiliser une instruction return dans ce rappel est uniquement pour contrôler le flux d'exécution dans cette fonction. Si vous voulez que l'exécution dans votre rappel se termine et n'exécute plus de code dans ce rappel, vous pouvez émettre un return; à ce stade.

Par exemple, vous auriez pu écrire votre code comme ceci sans instruction return:

function saveToTheDb(value) {  
  return new Promise(function(resolve, reject) {
    db.values.insert(value, function(err, user) { 
      if (err) {
        reject(err);
      } else {
        resolve(user);
      }
    });
  }
}

Dans ce cas, vous avez utilisé la clause if/else pour vous assurer que le flux de contrôle de votre fonction prend le chemin correct et qu'aucune variable return n'était nécessaire ou utilisée.


Un raccourci courant lors de la promotion de fonctions asynchrones comme ceci est:

function saveToTheDb(value) {  
  return new Promise(function(resolve, reject) {
    db.values.insert(value, function(err, user) { 
      if (err) return reject(err);
      resolve(user);
    });
  }
}

Ce n’est pas différent du bloc de code précédent d’un point de vue fonctionnel, mais c’est moins typé et plus compact. L'instruction return devant reject(err); sert uniquement à des raisons de contrôle pour empêcher l'exécution de l'instruction resolve(user); en cas d'erreur car le flux de contrôle souhaité consiste à appeler reject(err) sans exécuter quoi que ce soit d'autre dans le rappel.


En fait, l'instruction return de ce dernier bloc n'est même pas nécessaire dans ce cas particulier, car l'exécution d'une resolve() après une reject() ne fera rien car les promesses sont verrouillées selon la première résolution ou le premier rejet. Cependant, il est généralement considéré comme une mauvaise pratique d’exécuter du code non nécessaire, de sorte que beaucoup diraient qu’il est préférable d’utiliser un flux de structures de contrôle telles que if/else ou return pour exécuter uniquement le code nécessaire.

Donc, techniquement, cela fonctionnerait aussi, mais ce n’est pas considéré comme une pratique exemplaire car il exécute du code inutile et n’est pas aussi clairement structuré:

function saveToTheDb(value) {  
  return new Promise(function(resolve, reject) {
    db.values.insert(value, function(err, user) {
      if (err) reject(err);
      resolve(user);
    });
  }
}

Pour votre information, ce que vous faites ici est appelé "promisifying", ce qui crée une fonction asynchrone normale qui fonctionne avec un rappel dans une fonction qui retourne une promesse. Il existe des bibliothèques et des fonctions qui "promettent" une fonction ou un objet entier de fonctions (par exemple une API complète) pour vous dans un seul appel de fonction, de sorte que vous n'avez pas à le faire manuellement. Par exemple, j'utilise régulièrement Bluebird qui offre Promise.promisify() pour promettre une seule fonction ou Promise.promisifyAll() qui promet toutes les méthodes sur un objet ou un prototype. Ceci est très utile. Par exemple, vous pouvez obtenir des versions promises du module fs dans son intégralité avec ceci:

var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));

Ensuite, vous pouvez utiliser des méthodes qui renvoient une promesse telle que:

fs.readFileAsync("file.txt").then(function(data) {
    // do something with file.txt data here
});
36
jfriend00

Généralement, dans NodeJS, vous ne devriez pas beaucoup utiliser le constructeur de promesse.

Le constructeur de promesses est pour convertir des API qui ne renvoient pas de promesses en promesses . Vous devriez envisager d'utiliser une bibliothèque qui fournit promisification (même si vous utilisez des promesses natives), car elle fournit une alternative sûre qui ne comporte pas d'erreurs subtiles avec la logique de traitement des erreurs.

La promisification automatique est également considérablement plus rapide.

Cela dit, la réponse à votre question est "Oui".

C'est parfaitement sûr, il n'y a rien de spécial à propos des constructeurs de promesses - ils sont simplement du code JavaScript. Domenic discute de la conception du constructeur de promesses dans son blog .

Il est parfaitement sûr (comme toute autre fonction) de revenir plus tôt - il est en fait assez courant dans les fonctions asynchrones classiques.

(En outre, dans votre exemple de code, vous devriez simplement utiliser Promise.resolve, mais je suppose que c'était that simple uniquement parce que c'est un exemple).

Copié cette réponse d'un doublon

1