0

I'm a complete beginner in node.js so please excuse me if my question is foolish.Actually I'm trying to get some results from mongodb and print them but I'm unable to get desired output.

Code:

MongoClient.connect(url,function(err,db){
               if(err) throw err;

            var list=()=>{
                var arr=[]
                var blQ={blocked_user:data.tag_search_mail} 

                 db.collection("block_list").find(blQ,{"_id":0}).toArray((err,res)=>{

                         for(let i=0;i<res.length;i++){
                             arr.push(res[i]["blocker"])
                         }

                   });  
                 return arr  
            }
            var showList=(callback)=>{
               callback()
            }
            console.log(showList(list))//It's giving undefined
          // I wonder how can I print the returned array

What I tried after suggestion:

var list = (callback) => {
                var arr=[]

                    var blQ={blocked_user:data.tag_search_mail} 

                      db.collection("block_list").find(blQ,{"_id":0}).toArray((err,res)=>{

                              for(let i=0;i<res.length;i++){
                                  arr.push(res[i]["blocker"])
                              }
                              callback(arr);    
                        });  

            }

            list((arr) => {
                console.log(arr);
            })
Srinivas Nahak
  • 1,846
  • 4
  • 20
  • 45

3 Answers3

1

Rather than manual callbacks, I'd suggest you use the promise interface built into the node.js native interface for mongodb.

If you want to put this in a function and communicate back the result and close the DB when done, then you can do the following and return a promise from your function which the caller will use.

function getBlocked(data) {
    let openDb;

    close() {
        if (openDb) {
            openDb.close().catch(err => {
                console.log("Error closing db: ", err);
            })
        }
    }

    return MongoClient.connect(url).then(db => {
        openDb = db;
        const blQ = {blocked_user:data.tag_search_mail};
        return db.collection("block_list").find(blQ,{"_id":0}).toArray();
    }).then(results => {
        let blocked = results.map(item => item.blocker);
        close();
        return blocked;     // make this the resolved value of the promise
    }).catch(err => {
        close();
        throw err;          // rethrow to keep the promise rejected
    })
}

// usage
getBlocked(data).then(blocked => {
    // use blocked array here
}).catch(err => {
    // handle error here
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • sir thanks for your answer but I'm still getting **[ ]** – Srinivas Nahak Mar 31 '18 at 19:00
  • @NikhilKumar - Getting `[]` where? The ONLY place you can use the result is inside the `.then()` handler. This is asynchronous code. You have to code it and use it as such. – jfriend00 Mar 31 '18 at 19:16
  • I'm getting [] in .then() handler – Srinivas Nahak Mar 31 '18 at 19:37
  • @NikhilKumar - I'd have to see your exact code to help you debug it. – jfriend00 Mar 31 '18 at 19:38
  • sir I'm using your given code [this](https://stackoverflow.com/a/49591265/8953835) – Srinivas Nahak Mar 31 '18 at 19:41
  • @NikhilKumar - If you do `console.log(results)` right before the `let blocked = ...` statement, what do you see? If you do `console.log(blocked)` right before `return blocked`, what do you see? Are you passing the proper `data` value to `getBlocked(data).then(...)`? – jfriend00 Mar 31 '18 at 19:43
  • in all the places I'm getting **[ ]** – Srinivas Nahak Mar 31 '18 at 19:56
  • @NikhilKumar - Then, your query is not returning results so you need to examine what exactly you're passing your query. Are you 100% sure you're passing the right `data` value into the `getBlocked(data)` function so that `data.tag_search_mail` is the proper value in your query? – jfriend00 Mar 31 '18 at 20:01
  • yes the query is 200% correct I just have checked every part of the query tag_search mail everything as I had mentioned in this [question](https://stackoverflow.com/q/49589265/8027365) I was getting the result inside the for loop correctly so there's no chance for the query or data to be wrong – Srinivas Nahak Mar 31 '18 at 20:05
  • @NikhilKumar - My code is a bit different and it appears your query is finding now results in this code. I'm not asking if your query was correct in your code. I'm asking if it's correct here. Please insert `console.log(data.tag_search_mail)` and `console.log(blQ)` right before the `return db.collection(...)` line. – jfriend00 Mar 31 '18 at 20:08
  • @NikhilKumar - Also, what version of mongodb are you running? – jfriend00 Mar 31 '18 at 20:09
  • yes I've done that and it's showing the correct**search_mail** – Srinivas Nahak Mar 31 '18 at 20:10
  • db version v3.4.9 – Srinivas Nahak Mar 31 '18 at 20:11
  • Thanks a lot sir for your patient answers @jfriend00 – Srinivas Nahak Mar 31 '18 at 20:16
  • @NikhilKumar - What was the problem then? – jfriend00 Mar 31 '18 at 20:17
  • Actually I was querrying with the wrong email address it's my fault sir . I strongly regret and sorry for wasting your valuable time I should have checked the email address properly – Srinivas Nahak Mar 31 '18 at 20:19
  • @NikhilKumar - FYI, I posted this code here https://codereview.stackexchange.com/questions/190951/resource-closing-in-a-promise-chain to ask if there was a cleaner way to close the database in all return paths. You may want to follow that question just out of curiosity if people make any good suggestions. – jfriend00 Mar 31 '18 at 20:20
  • @NikhilKumar - OK, glad everything is working now. I'd strongly suggest you use the promise-based interface for all your mongodb work going forward. Much, much better than plain callbacks. – jfriend00 Mar 31 '18 at 20:20
  • Exacty sir indeed you're an ingenious and by the way you've taught me a lot of things today . I'm extremely thankful to you @jfriend00 – Srinivas Nahak Mar 31 '18 at 20:22
0

I would advise using Mongoose, a Node module that interfaces smoothly with MongoDB. Here is the documentation if you are interestd: http://mongoosejs.com/

However, to answer your question...

The problem with your code currently is that the showList function does not actually return anything. Here is what you want:

var list = (callback) => {
    // query mongodb here
    callback(arr);
}

list((arr) => {
    console.log(arr);
});

list takes in a function, eventually calling that function when it is done querying MongoDB. It will pass in the arr object. So when you call list later, you pass in a function that takes in the arr object, and you call console.log(arr) to print the result. Good luck!

darkterbears
  • 169
  • 12
  • sir thanks for your great answer but as that db.collection() is an asynchronous function that's why I'm getting result as **[]** so could you please help me to fix this – Srinivas Nahak Mar 31 '18 at 17:42
  • Then all you have to do is call the callback function inside the db.collection() asynchronous function. Unfortunately, I do not know of a way to make the MongoDB call synchronous. – darkterbears Mar 31 '18 at 17:42
  • sir please check the edit I've even added the callback() inside the db.collection but error is not changed – Srinivas Nahak Mar 31 '18 at 17:46
  • Can you do a `console.log(arr)` inside the db.collection() to see what is printed? The code looks like it should work unless there is a problem with the MongoDB query itself. – darkterbears Mar 31 '18 at 17:48
  • no actually what's happening is I'm getting result inside the for loop that means query is fine but I'm not getting result out of the loop – Srinivas Nahak Mar 31 '18 at 17:50
-1
var list =() => {
let arr =[];
for(let a =0 ; a< 20; a++)
arr.push(a);
return arr;
}

var show = (callback) => {
return callback()}

console.log("123",show(list));

Output:: 123 (20) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

Try just to add a return statement before calling the callback function and add the list function's return statement into database block. This might solve your problem.

MongoClient.connect(url,function(err,db){
           if(err) throw err;

        var list=(done)=>{
            var arr=[]
            var blQ={blocked_user:data.tag_search_mail} 

             db.collection("block_list").find(blQ,{"_id":0}).toArray((err,res)=>{

                     for(let i=0;i<res.length;i++){
                         arr.push(res[i]["blocker"])
                     }
                if(err) done(err);
                else done(null,arr);
               });  

        }
        var showList=(callback)=>{
           callback((err, result) => {
            if(err) console.log(err);
            else console.log(result):
})
        }
        showList(list);
Amanpreet
  • 219
  • 3
  • 10
  • This code is asynchronous. You can't just directly return the result and expect it to be there. – jfriend00 Mar 31 '18 at 19:24
  • @jfriend00 The arr will be returned only when the for loop execution will be done inside the database. Two things that were not correct in the user code first he was returning 'arr' outside the database block which is async and would be called even before the execution of db's is over. Second he was not returning the result coming from the callback function. – Amanpreet Mar 31 '18 at 19:38
  • The `list()` function has long since returned already. Your `return arr` is returning from the DB callback which just returns back into the database somewhere and has nothing to do with the return value for the `list()` function. This is a classic problem returning data from an asynchronous function. You can't return it synchronously. You have to return it via a callback or a promise which is what this whole question is about. You can read about the general topic here: https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call/14220323#14220323 – jfriend00 Mar 31 '18 at 19:41
  • @jfriend00 can you tell me is the above-edited code works well or is there some issue. – Amanpreet Mar 31 '18 at 20:17
  • I'm not the one who wrote the question. You will have to ask them. I've written a different answer that uses promises instead of plain callbacks. – jfriend00 Mar 31 '18 at 20:18