Nilay Modi
Nilay Modi

Reputation: 71

How do I resolve this knex.js promise correctly?

I'm using knex and this is my code to get a question_info object after requesting from the database.

let question_info = knex.select('id', 'question', 'pre_question', 'response_options_id').from('_questions').whereNot({'progress': 100}).andWhere({'school_id': school_id}).orderBy('date_created', 'asc')
        .map((question) => {
            //going through all possible questions
            helpers.debug("Question", question);
            //checking if there are responses
            return knex('_responses').where({'question_id': question.id, 'student_id': event.user.id}).first()
                .then((response) => {
                    //if no responses, return question_info object
                    if(!response){
                        return knex.select('options_json').from('_response_options').where({'id': question.response_options_id}).first()
                            .then((options) => {
                                return {
                                    question_id: question.id,
                                    question: question.question,
                                    pre_question: question.pre_question,
                                    response_options: JSON.parse(options.options_json)
                                }
                            });
                    }
                });     
        }).catch((e) => {
            console.error('Error', e);
        });

When the first question has already been answered, my return value shows up as null. How do I just have the returned array without null using knex correctly.

[
  null,
  {
    "question_id": "2",
    "question": "What is second question?",
    "pre_question": "Hey!!",
    "response_options": [
      {
        "title": "Yes",
        "value": "Yes"
      },
      {
        "title": "Maybe",
        "value": "Maybe"
      },
      {
        "title": "No",
        "value": "No"
      }
    ]
  },
  {
    "question_id": "3",
    "question": "Third Question?",
    "pre_question": "Yo",
    "response_options": [
      {
        "title": "Yes",
        "value": "Yes"
      },
      {
        "title": "Maybe",
        "value": "Maybe"
      },
      {
        "title": "No",
        "value": "No"
      }
    ]
  }
]

Upvotes: 0

Views: 821

Answers (1)

Mikael Lepistö
Mikael Lepistö

Reputation: 19718

Looks like your problem is that if second query indeed did return response you are not returning anything.

// this part of your code seems to be wrong
if (!response) {
  // return choices because there was no response found
  return knex('choices')...
}

It should be something like this:

// this part of your code seems to be wrong
if (!response) {
  // return choices because there was no response found
  return knex('choices')...
} else {
  return response;
}

EDIT this would be more or less how to do the same stuff with single query and joins (I didn't test this so it probably doesn't work, but it should give general idea how to achieve it):

let question_info = knex('_questions as q')
  .select(
     'id', 
     'question', 
     'pre_question', 
     'response_options_id',
     'r.id as r_id',
     'options_json'
  )
  .join('_responses as r', builder => {
    builder
      .on('q.id', 'r.question_id')
      .onVal('r.student_id', event.user.id);
  })
  .join('_response_options as ro', 'q.response_options_id', 'ro.id')
  .where('q.school_id', school_id)
  .whereNot('q.progress', 100)
  .whereNull('r.id')
  .orderBy('q.date_created', 'asc')
  .map(notAnsweredQuestion => {
    return {
      question_id: notAnsweredQuestion.id,
      question: notAnsweredQuestion.question,
      pre_question: notAnsweredQuestion.pre_question,
      response_options: JSON.parse(notAnsweredQuestion.options_json)
    };
  }).catch((e) => {
    console.error('Error', e);
  });

Upvotes: 1

Related Questions