How to return value in a javascript function

Asked

Viewed 252 times

0

I’m studying the framework Express to create a REST and when writing afunction I am unable to return the value that was processed.

When making the call to endpoint /test, the code below is executed:

 app.get('/test', (req, res) => {
    const value = getNextSequenceValue('cursoId');
    console.log(value);
    res.json(value);
});

So the function getNextSequenceValue runs the logic below:

function getNextSequenceValue(sequenceName)  {
    let returnNextValue = 0;
    MongoClient.connect(url, { useUnifiedTopology: true }, (err, client) => {

    //defini o banco de dados como 'test'
    const db = client.db('test');

    //verificar se a coleção 'counters' existe no banco de dados 'test'
    //se não existir, cria a coleção 'counters' no banco de dados 'test'
    db.listCollections({ name: 'counters' }).toArray((err, result) => {
        if (err) {
            throw 'error in list collections';
        };
        if (result.length == 0) {
            db.createCollection('counters');
        };
    });

    //defini a coleção como 'counters'
    const collection = db.collection('counters');


    //verifica se na coleção 'counters' existe um documento com o 'id' igual a variavel 'sequenceName'
    //se não existir cria o documento, com o valor da sequenciaValue = 0
    collection.findOne({ id: sequenceName }).then(result => {
        if (!result) {
            collection.insertOne({
                id: sequenceName,
                sequenceValue: 0
            });
        };
    }).catch(err => console.log(err));


    //incremente a sequenciaValue em 1 do id passado.
    collection.findOneAndUpdate(
        { id: sequenceName },
        { $inc: { sequenceValue: 1 } },
        { 'returnNewDocument': true }
    )
    .then(result => {    
        console.log(result.value.sequenceValue);
        returnNextValue = result.value.sequenceValue;
    })
    .catch(err => console.log(err))
    .finally(() => client.close());
});

return returnNextValue;
};

As can be seen in the excerpt:

.then(result => {    
        console.log(result.value.sequenceValue);
        returnNextValue = result.value.sequenceValue;
    })

Console output is correct, logic checks the required stock and displays on the console the value of the next sequence.

However, I cannot assign this value to the variable returnNextValue, soon the return is being 0.

  • Already tried leaving the getNextSequenceValue function as async and calling it with await in the express API?

  • no =/, I will search on that. thank you

3 answers

0

Hello, I’ve seen these problems before, I think it’s a variable scope problem, maybe if I use var in place of let, will work, but var is being deleted from the most modern codes. Below follows a solution, which hopefully will work.

I’ve done some local tests, with a simpler function than yours, and I think the following should work. if it doesn’t work, so I can help you, please inform which error appears in the console output.

async function getNextSequenceValue(sequenceName)  {
    let returnNextValue = 0;
    MongoClient.connect(url, { useUnifiedTopology: true }, (err, client) => {

    //defini o banco de dados como 'test'
    const db = client.db('test');

    //verificar se a coleção 'counters' existe no banco de dados 'test'
    //se não existir, cria a coleção 'counters' no banco de dados 'test'
    db.listCollections({ name: 'counters' }).toArray((err, result) => {
        if (err) {
            throw 'error in list collections';
        };
        if (result.length == 0) {
            db.createCollection('counters');
        };
    });

    //defini a coleção como 'counters'
    const collection = db.collection('counters');


    //verifica se na coleção 'counters' existe um documento com o 'id' igual a variavel 'sequenceName'
    //se não existir cria o documento, com o valor da sequenciaValue = 0
    collection.findOne({ id: sequenceName }).then(result => {
        if (!result) {
            collection.insertOne({
                id: sequenceName,
                sequenceValue: 0
            });
        };
    }).catch(err => console.log(err));


    //incremente a sequenciaValue em 1 do id passado.
    returnNextValue= await collection.findOneAndUpdate( //favor notar o await aqui, sem ele não funciona
        { id: sequenceName },
        { $inc: { sequenceValue: 1 } },
        { 'returnNewDocument': true }
    )
    .then(result => {    
        console.log(result.value.sequenceValue);
        return returnNextValue = result.value.sequenceValue;
    })
    .catch(err => console.log(err))
    .finally(() => client.close());
});

return returnNextValue;
};

Alternative

Alternatively, based on comment, you can do the following:

 app.get('/test', async  (req, res) => {
    const value = await getNextSequenceValue('cursoId');
    console.log(value);
    res.json(value);
});

But I’m not sure it will work because it looks like a variable scope problem, if the return returnNextValue do not receive the appropriate value, that would be the idea of the first solution proposal, the value will never be returned correctly.

Annex:

I used the code below to test:

async function rockit() {
  let aux;

  await Kitten.find({ name: /^fluff/ }).then(() => {
    return (aux = 2);
  });

  console.log(aux);
}
  • When informing the clause await is returned the error below: SyntaxError: await is only valid in async function

  • the function is defined as async ! how are you defining andasyncthis function? in the same file? for some reason the compiler is not seeing the async.

  • You noticed I put async at the beginning of the keyword function? Could be that.

  • Yes, I noticed, I put tbm, maybe it’s because of the framework express?

  • i test in express! besides this is Javascript, does not depend on express

  • the error that appears is when it is not set async

  • In your code, try this var returnNextValue = 0 in place of let returnNextValue = 0. In theory the variable will turn global.

  • @Thomas Erich Pimentel Please Look Up Response Update.

  • @Thomas Erich Pimentel could try the new answer?

  • Hello @Thomas Erich Pimentel worked???

  • Jorge, I appreciate the help, however, while reading better the documentation of the driver mongodb, I found that the return of the method findOneAndUpdade is a Promise and then refactored the code to work with that kind of feedback.

  • Yes, I was aware, so you need the await ! I’m glad it all worked out in the end!

Show 7 more comments

0

Could you try this solution too? I tested locally, with a simpler problem.

 app.get('/test', async (req, res) => {//async garante o uso de await
    const value = await getNextSequenceValue('cursoId');//pede para esperar
    console.log(value);
    res.json(value);
});

and then:

function getNextSequenceValue(sequenceName)  {
    let returnNextValue = 0;
    MongoClient.connect(url, { useUnifiedTopology: true }, (err, client) => {

    //defini o banco de dados como 'test'
    const db = client.db('test');

    //verificar se a coleção 'counters' existe no banco de dados 'test'
    //se não existir, cria a coleção 'counters' no banco de dados 'test'
    db.listCollections({ name: 'counters' }).toArray((err, result) => {
        if (err) {
            throw 'error in list collections';
        };
        if (result.length == 0) {
            db.createCollection('counters');
        };
    });

    //defini a coleção como 'counters'
    const collection = db.collection('counters');


    //verifica se na coleção 'counters' existe um documento com o 'id' igual a variavel 'sequenceName'
    //se não existir cria o documento, com o valor da sequenciaValue = 0
    collection.findOne({ id: sequenceName }).then(result => {
        if (!result) {
            collection.insertOne({
                id: sequenceName,
                sequenceValue: 0
            });
        };
    }).catch(err => console.log(err));


    //incremente a sequenciaValue em 1 do id passado.
    return collection.findOneAndUpdate(//esse vai retorna para da função 
        { id: sequenceName },
        { $inc: { sequenceValue: 1 } },
        { 'returnNewDocument': true }
    )
    .then(result => {    
        console.log(result.value.sequenceValue);
        return result.value.sequenceValue;//esse vai retorna para fora do then
    })
    .catch(err => console.log(err))
    .finally(() => client.close());
});

//return returnNextValue;
};

Please report if errors appear. In the function below it works:

rockit2();

async function rockit2() {
  console.log(await rockit());
}

function rockit() {
  let aux;

  return Kitten.findOneAndUpdate({ name: "fluffy" }, { name: "flu flu" }).then(
    () => {
      return 2;
    }
  );


}

0

When reading Node driver documentation for Mongodb:

Node.js Mongodb Driver API - findOneAndUpdate

We find that the return is:

Returns: Promise if no callback passed

That is, the return is a Promise therefore the return of function getNextSequenceValue will also be a Promise with this, I refactored the code as below:

Get method:

app.get('/test', (req, res) => {
    getNextSequenceValue('cursoId').then(result => {
        res.json(result);
    }).catch(err => {
        res.json(err);
    });
});

Function

function getNextSequenceValue(sequenceName) {
    return new Promise((resolve, reject) => {

        MongoClient.connect(url, { useUnifiedTopology: true }, (err, client) => {
            const db = client.db('test');

            db.listCollections({ name: 'counters' }).toArray((err, result) => {
                if (err) {
                    throw 'error in list collections';
                };
                if (result.length == 0) {
                    db.createCollection('counters');
                };
            });

            const collection = db.collection('counters');

            collection.findOne({ id: sequenceName }).then(result => {
                if (!result) {
                    collection.insertOne({
                        id: sequenceName,
                        sequenceValue: 0
                    });
                };
            }).catch(err => console.log(err));

            collection.findOneAndUpdate(
                { id: sequenceName },
                { $inc: { sequenceValue: 1 } },
                { 'returnNewDocument': true }
            ).then(result => {
                resolve(result.value.sequenceValue);
            }).catch(
                err => reject(err)
            ).finally(
                () => client.close()
            );
        });

    });
};

Browser other questions tagged

You are not signed in. Login or sign up in order to post.