Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
165 views
in Technique[技术] by (71.8m points)

node.js - Using SQL Server, nodejs and bycrypt, request ends before function is recieved

I'm fairly new to nodejs and have stumbled into a problem with my code.

The documentation for SQL Server and a guide I found on Youtube both handle their code this way, but after starting to use bycrypt I've noticed my function ends after the request is complete although I'm using .then().

Anyways, here's my code so far:

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;
    }
}

I tried logging both the request and the return value from the function getLoginDetails and the request log came faster, so I assume it's not waiting for the program to actually finish and I can't figure out why...

Sorry if that's obvious, but I'd love to get some help here!

EDIT:

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);
    }
});

This code works, but when I tried to encapsulate it in a function it still didn't work.

@Anatoly mentioned .query not finishing in time which makes sense, but I thought mssql .query is an async function?

question from:https://stackoverflow.com/questions/65872792/using-sql-server-nodejs-and-bycrypt-request-ends-before-function-is-recieved

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your problem arises from an wrong assumption that callbacks and promises are alike, but on the contrary callbacks don't "respect" promise/async constructs

When the program hits the bottom of getLoginDetails the progrm execution has already split into 2 branches one branch returned you the (empty) result whereas the other one still busy with crypto operations.

Though it is true that an async function always returns a promise but that doesn't cover any future callbacks that might execute inside it. As soon as node reaches the end of function or any return statement the async function's promise get resolved(therefore future callbacks are meaningless), what you can do instead is handroll your own promise which encampasses the callbacks as well

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);
        }

    });
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...