Подтвердить что ты не робот

Цепочка promises с последующим уловом

Я использую библиотеку Promise bluebird. Я хотел бы привязать promises и уловить определенные ошибки promises. Вот что я делаю:

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();
  });

Но если ошибка вызывается getSession, вызываются две catch, а также вторая then. Я хотел бы остановить распространение ошибки на первом catch, так что второй catch вызывается только тогда, когда getUser бросает, а второй then, когда getUser преуспевает. Что делать?

4b9b3361

Ответ 1

Обещание, возвращаемое методом .catch, по-прежнему будет разрешено с результатом обратного вызова, это не просто прекратит распространение цепочки. Вам потребуется либо разветкить цепочку:

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();
});

или используйте второй обратный вызов 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'));
});

В качестве альтернативы лучший способ - просто распространять ошибки через цепочку и вызывать next только в самом конце:

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);

Ответ 2

Поскольку вы используете bluebird для promises, вам действительно не нужна инструкция catch после каждой функции. Вы можете связать все ваши тогда вместе, а затем закрыть все это с помощью одного улова. Что-то вроде этого:

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);
  });

Предполагая, что сообщения об ошибках сообщают вам, что такое ошибка, все равно можно отправить сообщение об ошибке, такое как "session not found" или "user not found", но вам просто нужно посмотреть сообщение об ошибке, чтобы увидеть что это дает вам.

Примечание. Уверена, что у вас, вероятно, есть причина для вызова следующего, независимо от того, есть ли ошибка или нет, но может быть полезно запустить console.error(ошибка) в случае, если вы получите сообщение об ошибке. Кроме того, вы можете использовать некоторую другую функцию обработки ошибок, будь то console.error или res.send(404) или что-то подобное.