0

I have a function that GETs data from either mongodb or azure redis cache. I'm trying to set it up where it checks the cache first and then hits mongodb if cache is empty, but for some reason it's executing the mongodb code first. I created a promise to handle the order, but it's giving me an unhandled promise rejection error. I have a catch so I don't understand what the issue is. I appreciate any help!

console output


SETTING TRUE...
(node:27068) UnhandledPromiseRejectionWarning: Cache found
(node:27068) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise
which was not handled with .catch(). (rejection id: 1)
(node:27068) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero
exit code.

GET request



  const promise = new Promise((resolve, reject) => {
      client.get("directory", (err, reply) => {
        if (reply !== null) {
          console.log("SETTING TRUE...");
          redisReply = true;

          replyConverted = JSON.parse(reply);

          res.status(200).json({
            message: "Directory retrieved successfully!",
            posts: replyConverted,
            maxPosts: replyConverted
          });
          reject("Cache found);
        } else {
          resolve();
        }
      });
    }).then(res => {
      const postPerPage = 20;
      console.log("directory ID SECTION");

      var searchKey = new RegExp(req.query.keyword, "i");

      console.log("req.query.currentPage");
      console.log(req.query.currentPage);
      console.log(req.query.keyword);
      let currentPage = req.query.currentPage;

      console.log("REDIS RELY IS " + redisReply);
      console.log("GRABBING FROM COSMOSDB");
      User.countDocuments({
        $and: [{ username: searchKey }, { role: "Seller" }]
      })
        .then(docs => {
          console.log("COUNT");
          console.log(docs);
          let totalPosts = docs;
          User.find({
            $and: [{ username: searchKey }, { role: "Seller" }]
          })
            .select("_id username")
            .skip(postPerPage * (currentPage - 1))
            .limit(postPerPage)
            .then(documents => {
              res.status(200).json({
                message: "Directory retrieved successfully!",
                posts: documents,
                maxPosts: totalPosts
              });

              let docsString = JSON.stringify(docs);
              client.set("directory", docsString, (err, reply) => {
                console.log(reply);
              });
            });
        })
        .catch(err => {
          console.log("Skipped Mongodb");
        });

user6680
  • 79
  • 6
  • 34
  • 78
  • I think you have mixed up the `reject` and `resolve` in the first if else. Also when you find cached query in redis you should `return` so the execution stops. – C.Gochev Feb 09 '20 at 17:27
  • I'm rejecting it when the cache is found so that it doesn't hit the db. If I did resolve then it would go to next .then which I don't want when cache is found. Any chance you could provide an example of how to do it correctly? – user6680 Feb 09 '20 at 17:34

1 Answers1

1

You can make a function to first search the cache if found use it if not make query and then take callback with the result. In your case it might look something like this also you might want to make the key dynamic to correspond with your query

module.exports.findDirectory = function(client,query, callback){
    client.get(query, (err, reply) => {
     if (err) {
       callback(null);
    } else if(reply){

    callback(JSON.parse(reply));

    } else {
    User.countDocuments({
            $and: [{ username: query.searchKey }, { role: "Seller" }]
          })
            .then(docs => {
              console.log("COUNT");
              console.log(docs);
              let totalPosts = docs;
              let postsPerPage = 9;
              User.find({
                $and: [{ username: query.searchKey }, { role: "Seller" }]
              })
                .select("_id username")
                .skip(postPerPage * (query.currentPage - 1))
                .limit(postPerPage)
                .then(documents => {


         let docsString = JSON.stringify(docs);
         client.set(query, docsString, (err, reply) => {
                    console.log(reply);
                    callback(docs)
           });
       });
    }

  })

}

then use it in the route like this

dirsController.findDirectory(client,req.query,function(dirs){

   res.send(dirs)
}
C.Gochev
  • 1,837
  • 11
  • 21
  • It was saying query is undefined because I was using ```client.set``` with ```directory``` and then it was saying ```callback is undefined``` I made some modifications to your code to accommodate my use case and it's now returning the data successfully. If there's any feedback you wanna give. Let me know! https://pastebin.com/4H7UajFN – user6680 Feb 09 '20 at 18:41