Reputation: 2210
oModel.create("/SurveySet", oEntry, {
success: function(oData) {
for (var i = 0; i < questionData.questions.length; i++) {
var oEntry = {};
oEntry.SurveyId = oData.SurveyId;
oModel.create("/QuestionSet", oEntry, {
changeSetId: i.toString(),
success: function(oData) {
//Additional Processing
}
}
}
}
}
I'm Creating a SurveySet which returns a SurveyId.
For each Survey I need to create a QuestionSet in a FOR loop, returning the Data each time for additional processing.
The issue is in the order of execution. The for loop is incremented BEFORE the oData is retrieved from the 1st iteration.
E.g. if the for loop has 0 and 1, only the last element 1 is executed.
How do I delay the incrementation of the for loop until AFTER the oData is returned for the first iteratiion of the loop?
Upvotes: 1
Views: 4970
Reputation: 3948
I guess you access oEntry
or i
in the "Additional Processing".
The problem is that the inner success function with the additional processing is capturing the local variables defined outside like i
and oEntry
in a closure. The variables values are not copied.
i
, changes oEntry
and executes the oModel.create()
method.i
again, changes oEntry
and executes oModel.create()
again.So if you don't mind that your additional processing might happen out of order you can move the code inside the for loop into a separate function. When you call that function from the for loop the variable values will be copied so that each before mentioned closure will capture the copies which will not be changed by the for loop:
createSurvey: function(oEntry){
var that = this;
oModel.create("/SurveySet", oEntry, {
success: function(oData) {
for (var i = 0; i < questionData.questions.length; i++) {
that.createQuestion(oModel, questionData.questions, i, oData);
}
}
}
}
createQuestion(oModel, questions, i, survey){
var oEntry = {};
oEntry.SurveyId = survey.SurveyId;
oModel.create("/QuestionSet", oEntry, {
changeSetId: i.toString(),
success: function(oData) {
//Additional Processing
}
}
}
PS: You can also use questionData.questions.forEach(function(question, i){ ... });
to get the same effect. This time the anonymous function copies the values.
If you need to maintain strict order for your additional processing and send the requests sequencially to the backend, i would indeed recommend the use of promises:
createSurvey: function(oEntry){
var that = this;
oModel.create("/SurveySet", oEntry, {
success: function(oData) {
var promise = Promise.resolve();
questionData.questions.forEach(function(question, i) { //copy local variables
//Chain the promises
promise = promise.then(function(){ return that.createQuestion(oModel, question, i, oData)});
});
promise.then(function(){
//All done
})
.catch(function(){
//Error somewhere. remaining not executed
})
}
}
}
createQuestion(oModel, question, i, survey){ //returns a Promise now
var oEntry = {};
oEntry.SurveyId = survey.SurveyId;
return new Promise(function(resolve,reject){ //Wrap the UI5 stuff into a Promise
oModel.create("/QuestionSet", oEntry, {
changeSetId: i.toString(),
success: function(oData) {
//Additional Processing
resolve(oData);
},
error: reject
}
});
}
Upvotes: 3
Reputation: 134
You can push your Survey data to an array,then do the FOR loop
var data = [];
oModel.create("/SurveySet", oEntry, {
success: function(oData) {
data.push(oData.SurveyId);
}
}
$.each(data, function(index, value) {
for (var i = 0; i < questionData.questions.length; i++) {
var oEntry = {};
oEntry.SurveyId = value.SurveyId;
oModel.create("/QuestionSet", oEntry, {
changeSetId: i.toString(),
success: function(oData) {
//Additional Processing
}
}
}
)};
Upvotes: 1