1

I am trying to make this function make an appropriate callback. As it is written, the callback will be called twice - once for the synchronous 'if' statement and one for the asynchronous 'test2.save' statement. I am putting the counter code in just as an example that I tried. It doesn't work since the bottom if statement is synchronous. I already know what is wrong with this code, but I have no idea about how to make it better.

var postMatches = function(user1, userResults, callback) {
  User.find({}, {username: 1, testResults: 1}, (err, users) => {
    var counter = 0;
    users.forEach(function(user2){
      counter++;
      if(user1 !== user2.username && user2.testResults !== undefined) {
        var test1 = new Test({
          username: user1,
          match: user2.username,
          compatability: mbti[userResults][user2.testResults],
          alreadyMatches: false
        });

        test1.save( () => {
          var test2 = new Test({
            username: user2.username,
            match: user1,
            compatability: mbti[user2.testResults][userResults],
            alreadyMatches: false
          });

          test2.save( () => {
            if(counter === users.length) {
              callback();
            }
          });
        })
      } else {

        if(counter === users.length) {
          callback();
        }
      }
    })
  })
};
4
  • What is your use case ? Basically what you are trying to achieve ? What i can get is you have a db of users and trying to match some input user on basis of some param, can you explain a litle. Commented Aug 10, 2017 at 7:15
  • This function creates a link between two users in the Test collection. I need the callbacks mainly to test the function. I don't need the callbacks for my app to work, but I thought that this was a really interesting situation and wanted to hear some thoughts on it. Commented Aug 10, 2017 at 9:55
  • And what you want to achieve ? if user1 does not matches user2 then save the link else just return the callback ?why you are calling callback from test2.save ? Commented Aug 10, 2017 at 10:15
  • That is such a good point! I can't believe I missed it. I was just working with 2 user data. But do you have any idea where I can put a callback on this code? Commented Aug 10, 2017 at 11:35

1 Answer 1

1

From the comments and questions, compiled a code here. Use async module and forEach function to iterate over users list and return callback once done. Read about async and forEach. Let me know if this works for your use case.

var async = require('async')
var postMatches = function(user1, userResults, callback) {
  User.find({}, {username: 1, testResults: 1}, (err, users) => {
    var counter = 0;
    async.forEach(users,function(user2,iterate_callback){
      if(user1 !== user2.username && user2.testResults !== undefined) {
        var test1 = new Test({
          username: user1,
          match: user2.username,
          compatability: mbti[userResults][user2.testResults],
          alreadyMatches: false
        });

        test1.save( () => {
          var test2 = new Test({
            username: user2.username,
            match: user1,
            compatability: mbti[user2.testResults][userResults],
            alreadyMatches: false
          });

          test2.save( () => {
            iterate_callback();
          });
        })
      } else {
        iterate_callback();
      }
    },function(err){
      console.log("Done iterating");
      return callback();
    });
  })
};
Sign up to request clarification or add additional context in comments.

2 Comments

The test2.save -callback should call iterate_callback, otherwise the forEach never ends?
This worked like a charm. I didn't know about async foreach. Thanks for the lesson.

Your Answer

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