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.