I'm Loading multiple gltf models using an async function and then using .then()
I iterate through the results and add the models to my scene. It works perfectly fine until I remove one of the models from the source (the model I want to remove is larger than the rest), when I remove the model it seems like it's not waiting for all the promises to resolve before calling .then()
. Below is the loader function, what am I doing wrong?
'source' is just an array of objects containing the model file paths
The error occurs in the .then()
. If I remove one of the models (which is largest in size) from the 'source' array I get an error in the console: 'variant.components is not iterable'
async function modelLoader(source, loadingManager) {
const gltfLoader = new GLTFLoader(loadingManager);
const promises = [];
for (let i = 0; i < source.length; i++) {
promises.push(
new Promise((resolve) => {
const model = {}
gltfLoader.load(source[i].file, (gltf) => {
const children = [...gltf.scene.children];
console.log(children);
model.components = children;
resolve(model);
});
if (source[i].type === 'baseModel' || (source[i].type === 'variant' && source[i].viewPoints.file !== 'none')) {
gltfLoader.load(source[i].viewPoints.file, (gltf) => {
const viewPoints = [...gltf.scene.children];
model.viewPoints = viewPoints;
resolve(model);
});
} else if (source[i].type === 'baseModel' || (source[i].type === 'variant' && source[i].viewPoints.file === 'none')) {
model.viewPoints = 'none';
} else if (source[i].type === 'land') {
gltfLoader.load(source[i].buildingLine, (gltf) => {
const buildingLine = [...gltf.scene.children]
model.buildingLine = buildingLine
resolve(model)
})
}
})
);
}
return await Promise.all(promises);
}
const allModels = modelLoader(source, loadingManager)
allModels.then(result => {
for (const variant of result) {
if (variant.type === 'baseModel') {
const house = new THREE.Group()
for (const components of variant.components) {
house.add(components)
}
}
}
})
For anyone coming across the same issue, I found the solution, using await on each call of the gltfLoader fixed the issue.
async function modelLoader(source, loadingManager) {
const gltfLoader = new GLTFLoader(loadingManager);
const models = [];
for (let i = 0; i < source.length; i++) {
const model = {
name: source[i].name,
type: source[i].type,
isDefault: source[i].isDefault,
section: source[i].section,
isDetached: source[i].isDetached,
isInterior: source[i].isInterior,
price: source[i].price,
image: source[i].image,
};
const gltf = await new Promise((resolve) => {
gltfLoader.load(source[i].file, (gltf) => {
resolve(gltf);
});
});
const children = [...gltf.scene.children];
model.components = children;
if (
source[i].type === 'baseModel' ||
(source[i].type === 'variant' && source[i].viewPoints.file !== 'none')
) {
const viewPointsGltf = await new Promise((resolve) => {
gltfLoader.load(source[i].viewPoints.file, (gltf) => {
resolve(gltf);
});
});
const viewPoints = [...viewPointsGltf.scene.children];
model.viewPoints = viewPoints;
} else if (
source[i].type === 'baseModel' ||
(source[i].type === 'variant' && source[i].viewPoints.file === 'none')
) {
model.viewPoints = 'none';
} else if (source[i].type === 'land') {
const buildingLineGltf = await new Promise((resolve) => {
gltfLoader.load(source[i].buildingLine, (gltf) => {
resolve(gltf);
});
});
const buildingLine = [...buildingLineGltf.scene.children];
model.buildingLine = buildingLine;
}
models.push(model);
}
return models;
}