Вложенные условные обещания с использованием pg-prom и bluebird

Все, что я хочу сделать, это запустить запрос, проверить, зарегистрирован ли уже адрес электронной почты, и, если да, отклонить запрос, если не выполнить некоторую проверку, а затем создать пользователя в моей таблице пользователей. Это что-то вроде оболочки, код изначально был основан на https://github.com/vitaly-t/pg-promise-demo, этот код потрясающий, но я - нет. Обещания для меня совершенно бессмысленны, я понятия не имею, что мне возвращать и куда.

Этот код запускается и достигает того, что должен, но затем он попадает в ловушку и отправляет обратно «Cannot read property 'then' of undefined». Когда я пытаюсь связать второй .then так, чтобы он не находился внутри первого .then (), я получаю ошибки, которые я пытаюсь изменить после того, как он уже был отправлен.

Может кто-нибудь помочь мне понять, что здесь не так и как это исправить?

useradd: function (req, res) {
    db.users.findbyemail(req.body.email)
        .then(function(data){
            if( typeof data === undefined || data === null) {
                 db.users.add({
                    provider: 'local',
                    email: req.body.email, 
                    password: req.body.password, 
                    salt: 'salt', 
                    displayName: req.body.displayName })
                    .then(function(data){
                        res.json({
                            success: true,
                            data: "Account created"
                        })
                    }) 
            } else {
                 res.json({
                    success: false,
                    error: "Email address " + req.body.email + " is already registered on this site"
                })
            }
        })    

        .catch(function(error){
            res.json({
                success: false,
                error: error.message || error
            })
        })
}

person user2338041    schedule 08.09.2016    source источник
comment
Понятия не имею - возможно, вы захотите ознакомиться с моими практическими правилами.   -  person Bergi    schedule 08.09.2016
comment
Если вы получаете сообщение об ошибке Cannot read property 'then' of undefined в catch, это означает, что db.users.add не возвращает обещание, что, на мой взгляд, звучит как ошибка в библиотеке.   -  person Bergi    schedule 08.09.2016
comment
Это может произойти только тогда, когда ваш метод users.add не возвращает обещание. @Bergi LOL, ты разместил его на несколько секунд раньше меня :) Хотя это не связано с библиотекой, метод users.add - это его собственный код;)   -  person vitaly-t    schedule 08.09.2016
comment
Кроме того, вызов db.users.add вместо return db.users.add приведет к созданию кода без .catch.   -  person vitaly-t    schedule 08.09.2016
comment
Спасибо за ответы, ребята, я все еще не понимаю. Основываясь на ответах Виталия-Т (поскольку он написал и библиотеку, и демонстрацию, на которой я основываю этот код), я подумал, что мне нужно получить возврат перед вызовом db.users.add, поэтому я попробовал: return db. users.add ({который все еще выдает ошибку. Для справки, функция добавления в файле users.js выглядит так в коде Виталия-Т: add: name => rep.one(sql.add, name, user => user.id),, а мой выглядит так: add: (values) => { rep.one(sql.add, values, user => user.id)}, где я должен получить возврат? I   -  person user2338041    schedule 09.09.2016
comment
@ user2338041 вот тут твоя проблема, ты из метода ничего не возвращаешь. Вы сейчас серьезно спрашиваете нас, как вернуть значение из функции? :)   -  person vitaly-t    schedule 09.09.2016
comment
@ vitaly-t одна из моих многочисленных ошибок заключалась в том, что моя функция была заключена в {}, что останавливает подразумеваемый возврат. Теперь я вижу, что я новичок в стрелочных функциях, поэтому я не принимал это во внимание. Кроме того, поскольку я еще не в курсе обещаний, мне было интересно, нужно ли мне возвращать что-то конкретное, чтобы получить ожидаемые результаты. В любом случае спасибо, что нашли время помочь с моими вопросами.   -  person user2338041    schedule 10.09.2016


Ответы (1)


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

useradd: function (req, res) {
    return db.users.findbyemail(req.body.email)
       .then(function(data){
           return module.exports.validateUser(data, req);
        })
        .then(function(){
            return db.users.add({
                provider: 'local',
                email: req.body.email, 
                password: req.body.password, 
                salt: 'salt', 
                displayName: req.body.displayName })  
        })
        .then(function(){
            res.json({
                success: true,
                data: "Account created"
            })
            return "acct created";
        }) 
        .catch(function(error){
            res.json({
                success: false,
                error: error.message || error
            })
        })
},
validateUser: function(data, req) {
    console.log("got to validateUser, data " + data + " req " + req);
    if (typeof data !== 'undefined' && data !== null) {
        throw new Error("Email address " + req.body.email + " is already registered on this site");
    } else {
        //validation goes here
        return null;
}
},

//with the db.users.add function modified from the version in my comment to:
add: (values)  => {    
        var reponeres = rep.one(sql.add, values);
        return reponeres; 
    },
person user2338041    schedule 09.09.2016
comment
Вам следует рассмотреть возможность использования задач и транзакции при одновременном выполнении нескольких запросов. - person vitaly-t; 10.09.2016