2017-02-02 5 views
0

Я новичок в узле и изучаю все о обещаниях и pg-prom. Это то, что я хочу сделать, используя Экспресс и Pg-обещание:Как связывать утверждения вместе с помощью обещаний

  1. проверить электронную почту,
  2. если не найдено, проверьте имя пользователя,
  3. если не найдено создать новый пользователь.
  4. возвращение идентификатор пользователя

Я получил мой репо установить (db.users), который делает SQL, который работает большой.

В моем обработчике полномочий я не уверен, как заставить вызовы репо следовать друг за другом. Синтаксис кажется мне неуклюжим. Вот что у меня есть до сих пор:

exports.signup = function(req, res, next) { 

const username = req.body.username; 
const email = req.body.email; 
const password = req.body.password; 

// See if a user with the given email exists 
    db.users.byEmail({email: email}) 
     .then(user => { 
     if (user) { 
     return res.status(422).send({ error: 'Email is in use'}); 
     } else { 
     return null; <-- must I return something here? 
     } 
     }) 
    .then(() => { 
    db.users.getUsername({username: username}) 
    .then(user => { 
     if (user) { 
     return res.status(422).send({ error: 'Email is in use'}); 
     } else { 
     return null; <-- must I return something here? 
     } 

     ...etc 

    }) 

Возможно, pg-promises не соединяются вместе так? Должны ли они быть вложенными друг в друга или быть полностью отдельными блоками? Кроме того, не совсем уверен, куда идет улов. Я пробовал все, о чем я могу думать, следуя различным учебным пособиям, но я получаю такие ошибки, как «не могу установить заголовки, которые уже установлены», а «обещания не возвращаются». Если какой-либо человек может мне помочь, я бы очень признателен.

ответ

0

С руководством от vitaly-t я изменил его ответ, чтобы включить отдельные сообщения об ошибках в зависимости от того, какая вещь не удалась. Я также переместил следующий «затем» в блок транзакций, чтобы использовать «t» транзакции для следующего шага, который создает пользователя. Большое спасибо за жизненный опыт!

db.task(t => { 
    return t.users.byEmail({email}) 
     .then(user => { 
      if (user) { 
      throw new Error('Email is in use'); 
      } else { 
      return t.users.byUsername({username}); 
     } 
     }) 
     .then((user) => { 
      if (user) { 
       throw new Error('Username is taken'); 
      } else { 
       return t.users.addNew({username, email, password}); 
      } 
     }) 
}) 
.then(user => { 
    res.json({token: tokenForUser(user), username: user.username, aCheck: user.is_admin}); 
}) 
.catch(error => { 
    res.status(422).json({ 'error': error.message}); 
}); 
-1

Проверка username и email существование не зависит друг от друга. Думаю, Promise.all() подойдет вам больше, чем обещание цепочки.

exports.signup = function (req, res, next) { 
    const username = req.body.username; 
    const email = req.body.email; 
    const password = req.body.password; 

    Promise.all([ 
    db.users.byEmail({ 
     email: email 
    }), 
    db.users.getUsername({ 
     username: username 
    }) 
    ]).then((results)=> { 
    if (results[0] || results[1]) { 
     return res.status(422).send({ 
     error: 'Email is in use' // same error msg as per your snippet 
     }); 
    } 
    // here, code for creating a new user 
    }); 

}; 
+0

Это именно то, что 'пг-promise' документация говорит нам никогда не делать: https://github.com/vitaly-t/pg-promise/wiki/Common-Mistakes#tasks-versus-rootdirect- запросы. И если это не так уж плохо, его запросы зависят, они не могут выполняться независимо. –

+0

@ vitaly-t Да. Ты прав. Спасибо, что указали это. Вы можете ответить – Sridhar

1

Вы должны использовать task при выполнении нескольких запросов, так что они могут совместно использовать одно соединение, или же управление соединением будет страдать от проблем с производительностью.

db.task(t => { 
    return t.users.byEmail({email}) 
     .then(user => { 
      return user || t.users.getUsername({username}); 
     }); 
}) 
    .then(user => { 
     if (user) { 
      res.status(422).send({error: 'Email is in use'}); 
     } else { 
      // do something else 
     } 
    }) 
    .catch(error => { 
     // process the error 
    }); 

Он будет работать хорошо, предполагая, что ваши репозитории были созданы, как показано на pg-promise-demo.

Предыдущие 2 ответа были очень плохими, и полностью против того, что должно делать pg-promise. См. Tasks versus root/direct queries.

И при выполнении нескольких изменений вы обычно используете транзакцию - используйте tx вместо task.

+0

Спасибо, что помогли мне. Это полезно, но у меня есть один вопрос. Я хотел бы вернуть отдельную ошибку для каждого отказа. Если есть запись с этим письмом, я хочу вернуть «Электронная почта в использовании» и другая ошибка для имени пользователя. Из того, что я могу сказать из вашего кода, он возвращает ошибку электронной почты. Как мне это сделать? – Coco