Tengo un problema para resolver una promesa.
al cargar, mi secuencia de comandos tiene una promesa que deseo resolver cuando una función que contiene importaciones de archivos 3D termina de importarse.
el problema al que me enfrento es cómo hacer que las promesas resolve() se ejecuten cuando se ha cargado un modelo.
¿Hay alguna forma de obtener datos o algún tipo de señal del navegador cuando un modelo ha terminado de cargarse?
la siguiente es la promesa. deseo ejecutar res() cuando generateContent() haya terminado de importar objetos.
const myGeneralAsyncPromise = new Promise((res, rej) => { generateContent() if(some condition) res() // else rej() }) myGeneralAsyncPromise.then(allIsReady, notReadyYet)lo siguiente invoca una clase que crea un objeto dentro de generateContent().
var arrow3 = body(scene, world, 'static', 'arrow', { hx: 0.2, hy: 0.2, hz: 0.2 }, { x: 34.5, y: 3.35, z: 6 }, { x: 0, y:11, z: 0}); bodys.push(arrow3); var phone = body(scene, world, 'static', 'phone', { hx: 1.3, hy: 1.3, hz: 1.3 }, { x: 35.35, y:1.8, z: 6.5 }, { x: 0, y:0, z: 0}); bodys.push(phone); var pencil = body(scene, world, 'static', 'pencil', { hx: 2, hy: 2, hz: 2 }, { x: 35.5, y:1.8, z: 14 }, { x: 0, y:11, z: 0}); bodys.push(pencil);la siguiente es la importación real de cada objeto.
function body(scene, world, bodyType, colliderType, dimension, translation, rotation) { new GLTFLoader_js_1.GLTFLoader().load(`src/models/${colliderType}.glb`, function (gltf) { var model = gltf.scene; collider = gltf.scene model.scale.x = dimension.hx model.scale.y = dimension.hy model.scale.z = dimension.hz model.traverse(function (object) { if (object.isMesh) object.castShadow = true; }); model.position.x = translation.x model.position.y = translation.y model.position.z = translation.z model.rotation.x = rotation.x model.rotation.y = rotation.y model.rotation.z = rotation.z scene.add(model); var gltfAnimations = gltf.animations; var mixer = new THREE.AnimationMixer(model); var animationsMap = new Map(); gltfAnimations.filter(function (a) { return a.name != 'TPose'; }).forEach(function (a) { animationsMap.set(a.name, mixer.clipAction(a)); }); }); }para que conste: generar contenido () tiene más procesos que toman tiempo además de la importación, pero la importación es, con mucho, la más larga.
En pocas palabras: en mi promesa principal, me falta una condición que establecerá res () cuando los modelos hayan terminado de cargarse.
Debe hacer una promesa que se resuelva cuando se llame a la devolución de llamada de carga. En otras palabras, debe prometer .load .load() :
const promiseGLTFLoad = url => new Promise(resolve => new GLTFLoader_js_1.GLTFLoader().load(url, resolve));Con esta función ahora puede construir el procesamiento asíncrono:
async function body(scene, world, bodyType, colliderType, dimension, translation, rotation) { const gltf = await promiseGLTFLoad(`src/models/${colliderType}.glb`); var model = gltf.scene; collider = gltf.scene model.scale.x = dimension.hx /* ... etc ... */ scene.add(model); var gltfAnimations = gltf.animations; var mixer = new THREE.AnimationMixer(model); var animationsMap = new Map(); gltfAnimations.filter(a => a.name != 'TPose') .forEach(a => animationsMap.set(a.name, mixer.clipAction(a))); // Need to return the result!! return animationsMap; } Ahora, donde llamas al body , supongo que en generateContent : esa función debería recopilar las promesas que obtienes y luego esperarlas:
async function generateContent() { // ... var arrow3Promise = body(scene, world, 'static', 'arrow', { hx: 0.2, hy: 0.2, hz: 0.2 }, { x: 34.5, y: 3.35, z: 6 }, { x: 0, y:11, z: 0}); var phonePromise = body(scene, world, 'static', 'phone', { hx: 1.3, hy: 1.3, hz: 1.3 }, { x: 35.35, y:1.8, z: 6.5 }, { x: 0, y:0, z: 0}); var pencilPromise = body(scene, world, 'static', 'pencil', { hx: 2, hy: 2, hz: 2 }, { x: 35.5, y:1.8, z: 14 }, { x: 0, y:11, z: 0}); // Wait for all promises to resolve var bodys = await Promise.all(arrow3Promise, phonePromise, pencilPromise); // ... etc return bodys; // Maybe the caller needs them?? }Finalmente, el código del controlador principal haría esto:
async function main() { const bodys = await generateContent(); if (something is not right) throw new Error("my error"); // ... return bodys; // Maybe the caller needs them?? } main().then(allIsReady, failure); Tal vez realmente no necesites tantas capas. Puede verificar si algo no está bien al final de generateContent contenido y generar un error allí (que se traduce en una promesa rechazada). Y luego simplemente se convierte en:
generateContent().then(allIsReady, failure);Tenga en cuenta que no hay "notReadyYet". Una promesa resuelve o rechaza. Cuando se rechaza, debe considerarlo un fracaso. Aquí no hay un sentimiento de "todavía no".