Pg-promise:返回查询结果的正确方法

时间:2018-05-03 16:53:17

标签: node.js express asynchronous pg-promise

我想使用pg-promise检查用户名是否已被使用。

我使用以下查询:

this.db.one('SELECT EXISTS(SELECT 1 FROM users WHERE username = $1)', username);

我试图将这个查询封装在一个函数中,如果用户名存在,该函数只返回true,否则返回false。

类似的东西:

existsUsername(username){
  this.db.one('SELECT EXISTS(SELECT 1 FROM users WHERE username = $1)', username)
         .then(data => {
           if(data.exists == true){
             return true;
           } else {
             return false;
           }
         });
}

我可以这么简单地使用:

if(db.users.existsUsername(username)){
  // this username is already taken
}

但是,在查询完成之前评估if条件,导致未定义的变量。

返回查询结果的正确方法是什么?

编辑:外部调用者执行多个异步检查并返回用户是否有效:

function signUp(username, email, ...){
  // perform username existence check existsUser(username)

  // perform email existence check existsEmail(username)

  // ...

  // if everything OK, put user in DB
}

2 个答案:

答案 0 :(得分:2)

最简单的方法:

existsUsername(username) {
  return this.db.oneOrNone('SELECT * FROM users WHERE username = $1 LIMIT 1', username, a => !!a);
}

然后使用它:

db.users.existsUsername(username)
   .then(exists => {
      // exists - boolean
   })
   .catch(error => {
   });

你不能做if(db.users.existsUsername(username))这样的事情,它将同步代码与异步混合在一起。但如果您可以使用ES7语法,则可以执行if(await db.users.existsUsername(username))

如果您有三个独立的功能(checkUserNamecheckEmailcheckWhateverElse),并希望全部执行它们,那么这是最好的方法:

db.task(t => {
   return t.batch([checkUserName(t), checkEmail(t), checkWhateverElse(t)]);
})
.then(data => {
    // data = result of the batch operation;
})
.catch(error => {
   // error
});

与ES7语法相同:

db.task(async t => {
   const a = await checkUserName(t);
   const b = await checkEmail(t);
   const c = await checkWhateverElse(t);
   return {a, b, c};
})
.then(data => {
    // data = {a, b, c} object;
})
.catch(error => {
   // error
});

注意:为了共享连接,每个函数都应该针对t - 任务上下文执行查询。

答案 1 :(得分:1)

您无法以同步方式使用异步操作,您需要重写检查用户是否以异步方式存在的代码。即:

.card {
    position: relative;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-direction: column;
    flex-direction: column;
    min-width: 0;
    word-wrap: break-word;
    background-color: #fff;
    background-clip: border-box;
--> border: 1px solid rgba(0,0,0,.125); <-- This one right here
    border-radius: .25rem;
}

接下来在app中以类似

的方式使用它
border-radius: .25rem;

编辑:使用Promise.all执行多项任务,可能会遇到性能和连接问题(正如Vitaly所提到的那样)。

最好在db.batch

中使用db.task