0

I am programming a small Node.js server, to handle surveys. The surveys are stored on the server inside a global array.

When an user answers a question, the client will send the surveyID, the questionID and the answers to the server. On the server I then use Array.find() to determine the correct survey in the array, as well as the correct question inside the survey. Now I add the answers to the object. So far, so good. Works.

But if I wanted to do the manipulation in another function, I cannot simply pass the found survey object into it, because then it's not the same anymore, but a new one, and manipulating it inside the sub-function would not change the global survey object - is that right?

So what I currently do is to pass the IDs into the sub-function and use Array.find in it again. That way it works.

My question is: Is that the correct way to do this? Or is there another way?

Sample Code:

var surveys = [{
    id: 117171,
    flag_anonym: true,
    flag_live: true,
    status: "open",
    active_question: 0,
    questions: [
    {
        id: 117192,
        title: "Wie heißt die Hauptstadt von Deutschland?",
        typ: "singlechoice",
        answered_by_socket: [ ],
        answered_by_user: [ ],
        answers: [
            {
                id: 117188,
                title: "Mainz",
                votes_anonym: 11
            },
            {
                id: 117189,
                title: "Wiesbaden",
                votes_anonym: 0
            },
            {
                id: 117190,
                title: "Berlin",
                votes_anonym: 1
            },
            {
                id: 117191,
                title: "München",
                votes_anonym: 0
            }
        ]
    }
]}];

function updateSurvey(data) {
    var survey = surveys.find(function (s) {
        return s.id === data.survey_id;
    });
    if (typeof survey !== "undefined") {
        if(survey.flag_live) {
            // live survey, question can only be answered if active
            if (survey.active_question < survey.questions.length) {
                var question = survey.questions[survey.active_question];
                if (data.question_id === question.id) {
                    answerQuestion(data);
                }
            }
        }else {
            // question can always be answered
            answerQuestion(data);
        }
    }
}

function answerQuestion(data){
    // I have to do Array.find again
    var survey = surveys.find(function (s) {
        return s.id === data.survey_id;
    });
    var question = survey.questions.find(function (s) {
        return s.id === data.question_id;
    });
    question.answered_by_socket.push(data.socket_id);
    if (data.user_id) {
        question.answered_by_user.push(data.user_id);
    }
    // update answers
    question.answers = question.answers.map(function (a) {
        for (var i = 0; i < data.answers.length; i++) {
            var answer = data.answers[i];
            if (a.id === answer.id) {
                if (answer.checked) {
                    a.votes_anonym++;
                }
                return a;
            }
        }
        return a;
    });
}
Danmoreng
  • 2,367
  • 1
  • 19
  • 32
  • Offload your global survey array into a database like `MongoDB`. – Mike Eason May 02 '17 at 09:19
  • I am of the understanding that objects are passed by reference in Javascript, and that if you pass an object to a function and manipulate it, you are manipulating the original object and not a new copy of it. Have I misunderstood the question? – Martha May 02 '17 at 09:20
  • @MikeEason Ultimatively the data is stored in an SQL database, but since many users can answer a question at the same time, my approach was to use one array in memory to update everything and only save it to the database once. – Danmoreng May 02 '17 at 09:24
  • @Martha that is the idea, to manipulate the original object. But if I pass that object into another function, it is not the original object anymore? Or am I completely mistaken and it still is? – Danmoreng May 02 '17 at 09:25
  • @MikeEason Before the Node.js server came in, it was just PHP with an SQL database. The problem with it was: if many people answer at the same time, and the votes are stored as integer only, votes get lost since reading -> adding the vote -> saving to the database is too slow. – Danmoreng May 02 '17 at 09:29
  • @Danmoreng - What you have is almost like a proxy database between your SQL database and the Node server. While it is not necessarily a terrible idea it is **unnecessary**. Have faith in SQL, it is designed to handle thousands of concurrent queries and updates. Do away with your proxy global variable and save yourself a migraine. – Mike Eason May 02 '17 at 09:29
  • @Danmoreng, I would advise looking into the database speed issue. It is much better to fix the problem at the source rather than trying to work around it. – Mike Eason May 02 '17 at 09:31
  • @MikeEason Unfortunately, I don't have direct access to the database. It is only available through an REST API of the CMS we are using. So basically it means I need to use HTTP for reading and saving every time, although everything is on the same server. – Danmoreng May 02 '17 at 09:32
  • @Danmoreng If you just want to manipulate the object I think you're mistaken - see here: http://stackoverflow.com/a/13104500/4815046 – Martha May 02 '17 at 09:34

0 Answers0