web-dev-qa-db-fra.com

Enchaîner les promesses avec alors et attraper

J'utilise la bibliothèque Bluebird Promise. Je voudrais enchaîner les promesses et attraper les 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 générée par getSession, les deux catch sont appelées, ainsi que la seconde then. J'aimerais arrêter la propagation de l'erreur à la première catch, de sorte que la seconde catch ne soit appelée que lorsque getUser est lancée et la seconde then lorsque getUser réussit. Qu'est-ce que?

22

La promesse renvoyée par la méthode .catch sera toujours résolue avec le résultat du rappel, elle ne fera pas qu'arrêter la propagation de la chaîne. Vous devrez soit créer une branche dans 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 second 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'));
});

Sinon, le meilleur moyen consiste simplement à propager les erreurs dans la chaîne et à appeler next uniquement à la 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);
19
Bergi

Puisque vous utilisez bluebird pour vos promesses, vous n'avez en fait 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 ça:

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 disent quelle est l'erreur, il est toujours possible d'envoyer un message spécifique à l'erreur tel que "session introuvable" ou "utilisateur introuvable", mais vous devrez simplement regarder dans le message d'erreur pour voir ce que cela donne. vous.

Remarque: Je suis sûr que vous avez probablement une raison d'appeler la personne suivante, qu'il y ait ou non une erreur, mais il peut être utile d'introduire un fichier console.error (erreur) dans le cas où vous obtenez une erreur. Vous pouvez également utiliser une autre fonction de gestion des erreurs, qu'il s'agisse de console.error, de res.send (404) ou de quelque chose de similaire.

6
Mercury

Je l'utilise comme ça:

getSession(x)
.then(function (a) {
    ...
})
.then(function (b) {
    if(err){
        throw next(new Error('err msg'))
    }
    ...
})
.then(function (c) {
    ...
})
.catch(next);
0
Burak Dalkıran