1

I am new to NodeJS. I am using NodeJS on server side. I am trying to make a simple REST based GET request which takes search parameter searchvar from user and returns the matching records found in a JSON array. My server code is as follows:

var express = require('express');
var app = express();
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var ObjectId = require('mongodb').ObjectID;
var url = 'mongodb://localhost:27017/mydb';

app.get('/search', function(req, res) {
  res.set({ 'content-type': 'application/json; charset=utf-8' });
  res.header("Content-Type", "application/json; charset=utf-8");
  res.charset = 'utf-8';

  var searchvar = req.query.searchvar;

  if(searchvar != null) {
    var recordsArray = new Array();
    console.log("searchvar :: " + searchvar );

    MongoClient.connect(url, function(err, db) {
      var cursor = db.collection('myCollections').find({"name": new RegExp(searchvar)});
      cursor.each(function(err, doc) {
        //assert.equal(err, null);
        if (doc != null) {
          var tempObject = {"name": doc.name, "cat": doc.cat};
          recordsArray.push(tempObject);
          console.dir(doc);
        } else {
          db.close();
        }
      });

      if(recordsArray.length > 0) {
        console.log("if........");
        res.json({"status": "SUCCESS", "message": "The request processed successfully.", "records":recordsArray});
      } else {
        console.log("else........");
        res.json({"status": "FAILURE", "message": "No records found corresponding to given search query."});
      }
    });
  } else {
    res.json({"status": "FAILURE", "message": "The searchvar is missing."});
  }

  //res.send('id: ' + req.query.id);
});

app.listen(3000);

When I call it with RESTClient in a browser with following URL:

http://localhost:3000/search?searchvar=aa

I get following response:

{"status": "FAILURE", "message": "No records found corresponding to given search query."}

It is an async call. I want to know the process in server using which i can return the response when the processing is done and handle this async response on client side. Thanks in advance.

1
  • 1
    Any call to the server that you are treating as an async process will be handled strictly on the client side. On the client side, you are firing an AJAX call to a server, which then yields control back to the script that called it and returns an object that houses the state of the AJAX request. The code that created the AJAX request is responsible for checking periodically that AJAX object has received a response, and then it must act on it. Fortunately, there are many abstractions that make this easier through the form of promises and/or callbacks. this is true for browsers or node clients. Commented Mar 10, 2016 at 14:10

3 Answers 3

3

The response occurs because the if check:

if(recordsArray.length > 0) {
    console.log("if........");

is executed before the callback passed to the cursor.each method has completed its processing. As a result, the array is empty.

Proposed solution
The cursor.forEach method takes a callback function that is executed asynchronously. This means you can access the results of the callback's execution only within the callback itself (except you return a Promise object). A fix would be:

cursor.forEach(function(doc) {
  if (doc != null) {
    var tempObject = {"name": doc.name, "cat": doc.cat};
    recordsArray.push(tempObject);
    console.dir(doc);
  }
}, function(err) {
  if(recordsArray.length > 0) {
    console.log("if........");
    res.json({"status": "SUCCESS", "message": "The request processed successfully.", "records":recordsArray});
  } else {
    console.log("else........");
    res.json({"status": "FAILURE", "message": "No records found corresponding to given search query."});
  }
  db.close();
});
Sign up to request clarification or add additional context in comments.

2 Comments

The cursor.each method is deprecated, nor is it doing what you are claiming. The correct method would be cursor.forEach, which has "both" an iterator and a callback to indiccate when the iteration is actually complete. Both the OP's listing and your code are actually working "within" the iterator. In your case, both trying to send a response "and" hanging up the database connection on every iteration. This would fail badly.
Thank you very much for pointing this out. I've fixed the solution.
1

I think you're missing the callback parameter to the MongoClient Collection find() method. You should move your handling logic into the callback.

See these examples in the MongoDB documentation.

Your code would look something like this:

db.collection('myCollections').find({"name": new RegExp(searchvar)}).toArray(function(err, docs) {
    // iterate through docs; perform your logic
    db.close();
    res.json({...});
});

Comments

0

I think your best bet is to go through a Nodejs/MongoDB tutorial to understand how everything works. From a quick look at your code your response is not asynchronous. Any time the server responds right aways it's not async. Async is achieved on the server side when you implement something like Websockets or HTTP Callbacks.

I agree with Jim that the problem is probably in your client (please post the code if you still have questions). Generally a JS client achieves async by using callbacks or promises, but an async client does not require an async server. The reason it is common to make async client calls is so you don't lock up your GUI while waiting for a response from the server.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.