Видимость переменной функции [при асинхронном программировании]

Имеется загрузчик OBJLoader, работающий совместно с MTLLoader в TREE.JS. Вот часть кода:

	var door1ID;		
	var loaderDoor1 = new THREE.MTLLoader();

    loaderDoor1.load("Door1.obj.mtl", function(matDoor1){	
		matDoor1.preload();
		var objLoaderDoor1 = new THREE.OBJLoader(); 
		objLoaderDoor1.setMaterials(matDoor1);
		objLoaderDoor1.load("Door1.obj", function(meshDoor1){

	//----------------для ограничивающего объект параллелепипеда----------
		
			var door1Bbox = new THREE.Box3();
			door1Bbox.setFromObject(meshDoor1)
			var bboxDoor1Center = door1Bbox.getCenter().clone();
			bboxDoor1Center.multiplyScalar(-1);
				meshDoor1.traverse(function(child){
					if (child instanceof THREE.Mesh){
						child.geometry.translate(bboxDoor1Center.x, bboxDoor1Center.y, bboxDoor1Center.z); 
						
						 door1ID = child.id;//присваиваю переменной значение id 
						 //console.log(door1ID); // здесь значение переменной есть
					}
					//console.log(door1ID); //здесь undefined 
				});
				//console.log(door1ID); //здесь undefined 
			door1Bbox.setFromObject(meshDoor1);
	//------------------------------------------------
			cubeAs1.add(meshDoor1);
			meshDoor1.position.set((-bDoor1/2),0,(-cubeAs1Zobject));
			meshDoor1.rotation.y = Math.PI;
			//console.log(door1ID);   		
	    });
//console.log(door1ID);//здесь undefined 
	}); 
	//console.log(door1ID); //здесь undefined

//-------------------------------------------

Код работает, объект загружается. Но мне в дальнейшем нужен ID, который я присваиваю переменной door1ID. Однако он не виден вне функции, только внутри. Как вытащить его значение?

Значение переменной undefined потому важное для тебя значение создается позже того момента когда выполняется код который обращается к переменной. Гугли асинхронное программирование, коллбеки.

Самое простое что можно сделать в этом случае - написать функцию, которая получит значение на вход, и что-то сделает с ним. И вызвать эту функцию когда значение door1ID определено.

function logDoor(door) {
	console.log('door', door)
}

полный код

var door1ID;
var loaderDoor1 = new THREE.MTLLoader();

function logDoor(door) {
	console.log('door', door)
}

loaderDoor1.load("Door1.obj.mtl", function(matDoor1) {
	matDoor1.preload();
	var objLoaderDoor1 = new THREE.OBJLoader();
	objLoaderDoor1.setMaterials(matDoor1);
	objLoaderDoor1.load("Door1.obj", function(meshDoor1) {

		//----------------для ограничивающего объект параллелепипеда----------

		var door1Bbox = new THREE.Box3();
		door1Bbox.setFromObject(meshDoor1)
		var bboxDoor1Center = door1Bbox.getCenter().clone();
		bboxDoor1Center.multiplyScalar(-1);
		meshDoor1.traverse(function(child) {
			if (child instanceof THREE.Mesh) {
				child.geometry.translate(bboxDoor1Center.x, bboxDoor1Center.y, bboxDoor1Center.z);
				door1ID = child.id; //присваиваю переменной значение id 
				logDoor(door1ID)
				//console.log(door1ID); // здесь значение переменной есть
			}
			//console.log(door1ID); //здесь undefined 
		});
		//console.log(door1ID); //здесь undefined 
		door1Bbox.setFromObject(meshDoor1);
		//------------------------------------------------
		cubeAs1.add(meshDoor1);
		meshDoor1.position.set((-bDoor1 / 2), 0, (-cubeAs1Zobject));
		meshDoor1.rotation.y = Math.PI;
		//console.log(door1ID);   		
	});
	//console.log(door1ID);//здесь undefined 
});
//console.log(door1ID); //здесь undefined

Вот через промис решение:

var door1ID;
var loaderDoor1 = new THREE.MTLLoader();

door1ID = new Promise((resolve, reject) => {
    loaderDoor1.load("Door1.obj.mtl", function(matDoor1) {
        matDoor1.preload();
        var objLoaderDoor1 = new THREE.OBJLoader();
        objLoaderDoor1.setMaterials(matDoor1);
        objLoaderDoor1.load("Door1.obj", function(meshDoor1) {

            //----------------для ограничивающего объект параллелепипеда----------

            var door1Bbox = new THREE.Box3();
            door1Bbox.setFromObject(meshDoor1)
            var bboxDoor1Center = door1Bbox.getCenter().clone();
            bboxDoor1Center.multiplyScalar(-1);
            meshDoor1.traverse(function(child) {
                if (child instanceof THREE.Mesh) {
                    child.geometry.translate(bboxDoor1Center.x, bboxDoor1Center.y, bboxDoor1Center.z);
                    // присТекст "как есть" (без применения форматирования)ваиваю переменной значение id 

                    resolve(child.id)
                    //console.log(door1ID); // здесь значение переменной есть
                } else {
                    reject("don't have door Id");
                }
                //console.log(door1ID); //здесь undefined 
            });
            //console.log(door1ID); //здесь undefined 
            door1Bbox.setFromObject(meshDoor1);
            //------------------------------------------------
            cubeAs1.add(meshDoor1);
            meshDoor1.position.set((-bDoor1 / 2), 0, (-cubeAs1Zobject));
            meshDoor1.rotation.y = Math.PI;
            //console.log(door1ID);   		
        });
        //console.log(door1ID);//здесь undefined 
    });
    //console.log(door1ID); //здесь undefined
});

door1ID
    .then((id) => {console.log(id)})
    .catch((error) => {console.log(error)});
1 лайк

Добрый день. Спасибо за помощь. Сделал promise, как ты посоветовал.
Однако в консоль выводится “don’t have door Id”. Хотя перед строчкой
resolve(child.id)
значение child.id определено (19).
Если я после
.catch((error) => {console.log(error)});
добавляю
console.log(door1ID);
то в консоли сообщение выводится сообщение “Promise { : “pending” }”