我是nodejs的新手,我的代码遇到了一个问题。
SQL Server的文档和我在Youtube上找到的指南都以这种方式处理他们的代码,但在开始使用加密后,我注意到我的功能在请求完成后结束,尽管我使用.then()
。
无论如何,这是我目前为止的代码:
router.post('/login', (req, res) => {
getLoginDetails(req.body.username, req.body.password).then(result => {
console.log(result);
res.json(result);
})
});
async function getLoginDetails(username, password) {
await pool1Connect;
try {
const request = pool1.request();
request.input('username', sql.NVarChar, username);
request.query('SELECT * FROM users WHERE username = @username', (err, result) => {
if (err) {
return ({err: err})
}
if (result.recordset.length > 0) {
bcrypt.compare(password, result.recordset[0].user_password, (err, response) => {
if (response) {
console.log(result.recordset);
return(result.recordset);
} else {
return({message: "Wrong password or username!"})
}
})
return(result)
} else {
return({message: "user not found!"})
}
})
} catch (err) {
return err;
}
}
我尝试记录请求和函数getLoginDetails
的返回值,请求日志来的更快,所以我认为它不是等待程序实际完成,我不知道为什么…
很抱歉,如果这是显而易见的,但我希望得到一些帮助!
编辑:
router.post('/login', async (req, res) => {
// res.send(getLoginDetails(req.body.username, req.body.password))
await pool1Connect
try {
const request = pool1.request();
request.input('username', sql.NVarChar, req.body.username);
request.query('SELECT * FROM users WHERE username = @username', (err, result) => {
console.log(result);
bcrypt.compare(req.body.password, result.recordset[0].user_password, (err, response) => {
if (response) {
res.send(result);
} else {
res.send('wrong password')
}
})
//res.send(result)
})
} catch (err) {
res.send(err);
}
});
这段代码可以工作,但是当我试图将它封装在一个函数中时,它仍然不能工作。
@Anatoly提到.query
没有及时完成,这是有道理的,但我认为mssql.query
是一个异步函数?
你的问题来自于一个错误的假设,即回调和承诺是相似的,但恰恰相反,回调并不"尊重"。承诺/异步结构
当程序到达getLoginDetails
的底部时,程序执行已经分成两个分支,一个分支返回(空)结果,而另一个分支仍然忙于加密操作。
虽然async函数总是返回一个promise,但这并不包括任何可能在其中执行的未来回调。一旦节点到达函数或任何返回语句的结束,异步函数的承诺就会被解决(因此未来的回调是无意义的),你可以做的是手滚你自己的承诺,它也包含回调
router.post('/login', (req, res) => {
getLoginDetails(req.body.username, req.body.password))
.then((result)=>{
res.send(result);
})
.catch((err)=>{
res.send(err);
})
});
async function getLoginDetails(username, password) {
await pool1Connect
return new Promise( (resolve,reject) => {
try {
const request = pool1.request();
request.input('username', sql.NVarChar, username);
request.query('SELECT * FROM users WHERE username = @username', (err, result) => {
console.log(result);
bcrypt.compare(password, result.recordset[0].user_password, (err, response) => {
if (response) {
resolve(result);
} else {
resolve('wrong password')
}
})
})
} catch (err) {
reject(err);
}
});
}
您没有返回任何结果到getLoginDetails
。您可以使用request.query
和bcrypt.compare
(如果有的话)的async
版本,或者将request.query
包装为new Promise((resolve, reject)
,如下所示:
const asyncResult = new Promise((resolve, reject) => {
request.query('SELECT ...
...
if (err) {
resolve({err: err}) // replace all return statements with resolve calls
}
...
})
const queryResult = await asyncResult;