I have a very confusing bug…
I have a data model with a three level hierarchy: Survey has one or more Respondents has one or more QuestionResponses (where each QuestionResponse connects back to a Question under the Survey). Each Thing has a collection of child Things.
I have created a client-side Action plugin with some fairly simple Javascript that tries to export that data as a CSV, with one row per Respondent - there are a set of columns coming from the Respondent thing, and then some more columns for each QuestionResponse (q1_field, q2_field etc). I have to flatten the data this way for various legacy integration reasons.
My client-side action can export a dummy CSV with no problem. The challenge comes when I try and populate the data…
The function looks like this (I’ve cut a load of redundant stuff out, this is the guts):
function action(properties, context) {
var respondents = properties.survey.get('respondents_list_custom_respondent');
respondents = respondents.get(0, respondents.length());
const rows = [];
console.log(respondents.length+' respondents');
for (var i=0; i<respondents.length; i++) {
console.log('Row '+i);
const row = {
response_date: respondents[i].get('response_date_date'),
// etc
};
// then add each question's response
var questionResponses = respondents[i].get('responses_list_custom_dlrespondentresponse');
questionResponses = questionResponses.get(0, questionResponses.length());
for (var j=0; j<questionResponses.length; j++) {
console.log('Question '+i+'.'+j);
const question = questionResponses[j].get('question_custom_dlsurveyquestions');
const prefix = 'q' + question.get('order_number') + '_';
const type = question.get('type_option_questiontype');
if (type.get('data_value')) {
row[prefix+'value'] = question.get('non_video_response_text');
}
// etc
}
rows.push(row);
};
// CSV stuff - not the problem
}
I have a sample survey with 3 questions and 2 respondents, each of whom completed all 3 questions. I’d therefore expect to get back 2 rows with the core columns plus 3 sets of question-specific columns.
In actual fact, I get less data - and when I log the loops, the entire function appears to have been run multiple times - this is consistent whether I write the loops like this or with forEach() functions. The logging comes out like this:
2 respondents
2 respondents
Row 0
Question 0.0
2 respondents
Row 0
Question 0.0
Question 0.1
2 respondents
Row 0
Question 0.0
Question 0.1
2 respondents
Row 0
Question 0.0
Question 0.1
Row 1
Question 1.0
2 respondents
Row 0
Question 0.0
Question 0.1
Row 1
Question 1.0
Question 1.1
2 respondents
Row 0
Question 0.0
Question 0.1
Row 1
Question 1.0
Question 1.1
Question 1.2
2 respondents
Row 0
Question 0.0
Question 0.1
Row 1
Question 1.0
Question 1.1
Question 1.2
The rows array comes back with the first row containing only two questions, and the second containing them all. If I comment out the inner loop, I get this:
2 respondents
2 respondents
Row 0
2 respondents
Row 0
Row 1
It’s possible I’m just being very stupid but this seems like fairly simple logic, and I don’t think I’ve messed up the loops… or am I doing something stupid?
My guess is that Bubble is lazy loading the data, and simulating a synchronous method where in reality that lazy loading is done asynchronously, and the way it does that is broken?
Cheers!