There are a number of issues in the above code snippet, caused by the fact that creating objects is asynchronous, and the order in which objects are created is non deterministic:
It assumes that the creation of the Label object is finished before the Option objects are created. But because of it being asynchronous, the creation of the Label object might not be finished yet when the first Option callback is reached, in which case LabelGuid will be undefined.
In the Option callback, the loop counter i is used to set the OptionName. But the first callback will only be called after the loop is finished, which is why in the callback i will always have its final value. See also this example, where a timeout is used to mimic asynchronicity.
The first issue can be fixed by splitting the code in two and creating the Option objects only after the creation of the Label object is finished. The second issue can be fixed by using a forEach, which creates a new function scope for every item, instead of a normal for loop. See the following example.
function createLabelObject(callback) {
mx.data.create({
// ...
callback: function(obj) {
callback(obj);
}
});
}
function createOptionObjects(labelObj) {
selectedOptions.forEach(function(option) {
mx.data.create({
// ...
callback: function(obj) {
obj.set("OptionName", option);
obj.addReference("TestSuite.Option_Label", labelObj.getGuid());
}
});
});
}
createLabelObject(function(labelObj) {
createOptionObjects(labelObj);
});
You could do the creation of your option entity objects in the callback in which you created the label entity object.
Since the mx.data.create function is async you never know when it is finished making them sequential means using the call back functions to set the correct order.