Enchaîner les promesses avec Puis et attraper

J'utilise la bibliothèque Bluebird Promise. Je voudrais enchaîner les promesses et attraper des erreurs de promesses spécifiques. Voici ce que je fais:

getSession(sessionId)
  .catch(function (err) {
    next(new Error('session not found'));
  })
  .then(function (session) {
    return getUser(session.user_id);
  })
  .catch(function (err) {
    next(new Error('user not found'));
  })
  .then(function (user) {
    req.user = user;
    next();
  });

, Mais si une erreur est renvoyée par getSession, les deux catch sont appelés, ainsi que le deuxième then. Je voudrais arrêter la propagation de l'erreur au premier catch, de sorte que le second catch ne soit appelé que lorsque getUser lance, et le second then lorsque getUser réussit. Que faire?

21
demandé sur Alexandre Kirszenberg 2014-07-08 00:38:43

2 réponses

La promesse renvoyée par la méthode .catch sera toujours résolue avec le résultat du rappel, elle n'arrête pas seulement la propagation de la chaîne. Vous aurez soit besoin de brancher la chaîne:

var session = getSession(sessionId);
session.catch(function (err) { next(new Error('session not found')); });
var user = session.get("user_id").then(getUser);
user.catch(function (err) { next(new Error('user not found')); })
user.then(function (user) {
    req.user = user;
    next();
});

Ou utilisez le deuxième rappel à then:

getSession(sessionId).then(function(session) {
    getUser(session.user_id).then(function (user) {
        req.user = user;
        next();
    }, function (err) {
        next(new Error('user not found'));
    });
}, function (err) {
    next(new Error('session not found'));
});

Alternativement, la meilleure façon serait de simplement propager les erreurs à travers la chaîne, et d'appeler next seulement à la toute fin:

getSession(sessionId).catch(function (err) {
    throw new Error('session not found'));
}).then(function(session) {
    return getUser(session.user_id).catch(function (err) {
        throw new Error('user not found'));
    })
}).then(function (user) {
    req.user = user;
    return null;
}).then(next, next);
18
répondu Bergi 2014-07-07 20:58:43

Puisque vous utilisez bluebird pour les promesses, vous n'avez pas besoin d'une instruction catch après chaque fonction. Vous pouvez enchaîner tous vos thens ensemble, puis fermer le tout avec une seule prise. Quelque chose comme ceci:

getSession(sessionId)
  .then(function (session) {
    return getUser(session.user_id);
  })
  .then(function (user) {
    req.user = user;
    next();
  })
  .catch(function(error){
    /* potentially some code for generating an error specific message here */
    next(error);
  });

En supposant que les messages d'erreur vous indiquent quelle est l'erreur, il est toujours possible d'envoyer un message spécifique à l'erreur comme 'session not found' ou 'user not found', mais vous devrez simplement regarder dans le message d'erreur pour voir ce qu'il donne vous.

Note: je suis sûr que vous avez probablement une raison d'appeler next, qu'il y ait une erreur ou non, mais il pourrait être utile de lancer une console.erreur (erreur) dans le cas où vous obtenez une erreur. Alternativement, vous pouvez utiliser une autre fonction de gestion des erreurs, que ce soit une console.erreur, ou res. send (404), ou quelque chose du genre.

6
répondu Mercury 2014-07-07 21:07:22