Search code examples
node.jsexpresspgpg-promise

return does not terminate a promise/then chain


I have the following code that I use to signup users.

const pgp = require('pg-promise')();
const crypto = require('./crypto.js');

const db = pgp(connection);

const querySelect = (text, params) => {  
  const s = pgp.as.format(text, params);  
  return db.any(s)
  .then(data => {    
    return data;    
  })
  .catch(error => {
    return error;
  });
}

const queryInsert = (text, params) => {  
  const s = pgp.as.format(text, params);  
  return db.one(s)
  .then(data => {    
    return data;    
  })
  .catch(error => {
    return error;
  });
}

const signup = (user) => {
  return new Promise((resolved, rejeted)=>{    
    return querySelect('select username from user WHERE username = $1', [user.username])      
    .then(res => {
      if (res.length == 0) {              
        return true;
      }      
      return resolved(false);  //SHOULD STOP + RETURN HERE                                 
    })
    .then(hashPasswordRes=>{      
      return crypto.hashPassword(user.password);
    })
    .then(queryRes=>{      
      if (queryRes) {
        return queryInsert('insert into user (username,password) values ($1,$2) RETURNING id', 
        [user.username, user.password]);      
      } else {            
        return rejeted('error while signup');
      }
    })
    .then(res=>{
      resolved(true);          
    })
    .catch(error => {
        return rejeted('error while signup');
    });// catch
  }) //promise
};//signup

exports.signup = signup;

This is basically the whole file. Pretty simple I guess.

The problem is that in the point where I comment SHOULD STOP + RETURN HERE it does return false (so that means that the is already an existing username like the one inserted) but the execution never stops, so the user ends up saved in the database (even though the return resolved(false); is executed).

What am I doing wrong here? This used to work when I had just the pg module in my code. When I used pg-promise, it started having this issue.

Frankly, I dont have a clue why the "return" doesnt also stop the function execution. Please advice

(node 8.11.1, express 4.16.3, pg 7.4.2, pg-promise 8.4.4)

Thanks

EDIT

for the record, here is the same file without pg-promise , that works just fine. The vars names change, but you can see the logic. I tried to use the same logic with pg-promise

  const crypto = require('./crypto.js');
  const {Client} = require('pg');


const getuser = (mail, client) => {
  return new Promise((resolved, rejeted)=>{
    return client.query('select mail from user WHERE mail = $1',[mail])
    .then(res => {
      resolved(res.rows);
     })
     .catch(e => {
        rejeted(e);
        client.end();
     }); // catch
  })//promise
} //getUser


const signup = (user) => {
  return new Promise((resolved, rejeted)=>{
    client.connect().then(() => {
        getuser(user.email, client) 
        .then(getUserRes => {
          if (getUserRes.length==0) {
            return true;
          }
          client.end();
          return resolved(false);
        })
        .then(hashPasswordRes=>{
            return crypto.hashPassword(user.password);
        })
        .then(queryRes=>{
          if (queryRes) {
            const nowtime = new Date();
            return client.query('insert into user(mail, password) values ($1,$2)',
            [user.email, queryRes])
          } else {
            client.end();
            return rejeted('some error');
          }
        })
        .then(res=>{
          resolved(true);
          client.end();
        })
    }) // client.connect then
    .catch(error => {
      rejeted('some error');
      client.end();
    });// catch
  }) //promise
};//signup


exports.signup = signup;

Solution

  • The return ends the current function that is running, which is not the promise chain. So this part:

    return resolved(false);  //SHOULD STOP + RETURN HERE 
    

    Ends the current function, which is:

    res => {
          if (res.length == 0) {              
            return true;
          }      
          return resolved(false);  //SHOULD STOP + RETURN HERE                                 
        }
    

    Notices that the arrow declares a function.

    If you wanna stop a chain you can do something like this

    Promise.resolve(res)
    .then(res => {
        if (shouldKeepGoing(res)) {
            return allTheOtherPromises(res)
        }
        return true
    })
    
    const allTheOtherPromises = res => {
        // Here you do all the promises you were doing
    }