У меня есть модуль, который возвращает массив, состоящий из данных JSON и объектов изображения. Поскольку как загрузка JSON (из других файлов), так и объекты изображения требуют времени, мне нужно, чтобы мой модуль возвращал массив только после завершения.
В настоящее время модуль всегда возвращает "undefined" в других модулях, и я считаю, что это потому, что модуль не ждет возврата, как я ожидаю, (но я не уверен). Или, потому что другой модуль, использующий этот модуль Atlas, объявляет его как переменную, прежде чем он что-либо вернет.
Отредактировано, чтобы показать, как я определяю/требую модулей * Снова отредактировано, чтобы показать больше кода *
Живой код можно увидеть здесь.
Вот мой модуль плитки-атласа:
define( function() {
var tilesheetPaths = [
"tilesheets/ground.json",
"tilesheets/ground-collision.json",
"tilesheets/objects-collision.json"
];
var tileAtlas = [ ];
function loadAtlasJSON() {
for (var i = 0; i < tilesheetPaths.length; i++) {
loadJSON(
{
fileName: tilesheetPaths[ i ],
success: function( atlas ) {
addToTileAtlas( atlas );
}
}
);
}
};
function addToTileAtlas( atlas ) {
atlas.loaded = false;
var img = new Image();
img.onload = function() {
atlas.loaded = true;
};
img.src = atlas.src;
// Store the image object as an "object" property
atlas.object = img;
tileAtlas[ atlas.id ] = atlas;
}
// Returns tileAtlas[ ] once everything is loaded and ready
function tileAtlasReady() {
if ( allJSONloaded() && allImagesLoaded() ) {
console.log("TileAtlas ready");
return tileAtlas;
}
console.log("TileAtlas not ready");
setTimeout(tileAtlasReady, 10);
};
// Checks to make sure all XMLHttpRequests are finished and response is added to tileAtlas
function allJSONloaded() {
// If the tilesheet count in tileAtlas !== the total amount of tilesheets
if ( Object.size(tileAtlas) !== tilesheetPaths.length ) {
// All tilesheets have not been loaded into tileAtlas
console.log("JSON still loading");
return false;
}
console.log("All JSON loaded");
return true;
};
// Checks that all img objects have been loaded for the tilesheets
function allImagesLoaded() {
for ( var tilesheet in tileAtlas ) {
if (tileAtlas[tilesheet].loaded !== true) {
console.log("Images still loading");
return false;
}
}
console.log("All images loaded");
return true;
};
// Loads the JSON/images
loadAtlasJSON();
// Module should only return when tileAtlasReady() returns
return tileAtlasReady();
} );
И это моя функция loadJSON из моего lib:
window.loadJSON = function( args ) {
var xhr = new XMLHttpRequest();
xhr.overrideMimeType( "application/json" );
xhr.open( "GET", args.fileName, true );
xhr.onreadystatechange = function () {
if ( xhr.readyState == 4 ) {
if ( xhr.status == "200" ) {
// Check that response is valid JSON
try {
JSON.parse( xhr.responseText );
} catch ( e ) {
console.log( args.fileName + ": " + e );
return false;
}
args.success( JSON.parse(xhr.responseText) );
// xhr.status === "404", file not found
} else {
console.log("File: " + args.fileName + " was not found!");
}
}
}
xhr.send();
}
И модуль, загружающий мой модуль плитки-атласа:
define( ['data/tile-atlas'], function( tileAtlas ) {
function displayImages() {
// Code
};
// Returns undefined
console.log(tileAtlas);
displayKey();
} );
И вот как выглядит результат:
[12:14:45.407] "JSON still loading"
[12:14:45.407] "TileAtlas not ready"
[12:14:45.408] undefined
[12:14:45.428] "JSON still loading"
[12:14:45.428] "TileAtlas not ready"
[12:14:45.469] "All JSON loaded"
[12:14:45.470] "Images still loading"
[12:14:45.470] "TileAtlas not ready"
[12:14:45.481] "All JSON loaded"
[12:14:45.481] "Images still loading"
[12:14:45.481] "TileAtlas not ready"
[12:14:45.492] "All JSON loaded"
[12:14:45.492] "All images loaded"
[12:14:45.492] "TileAtlas ready"
"undefined" - это когда я console.log мой модуль Atlas из другого модуля, который зависит от модуля Atlas.
Я не уверен, что модуль Atlas возвращает что-то прежде, чем он захочет, или другие модули, объявляющие модуль Atlas как переменную, прежде чем что-то вернут.
Но если это последний, есть ли способ сделать так, чтобы модули не запускались до тех пор, пока их зависимости не закончили что-то возвращать?
Я совершенно новичок в Require.js и AMD: этот подход по своей сути ошибочен? Я бы подумал, что использование AMD с чувствительными к нагрузке модулями является обычным явлением.
Спасибо за вашу помощь.
РЕДАКТИРОВАТЬ. Изучив исходный код другой игры, я понял, что могу просто загружать файлы jSON с помощью плагина require.js вместо реализации XHR в моем модуле. Это намного проще, так как мне не нужно будет справляться со сложностью ожидания XHR внутри модуля. Вот как это делает BrowserQuest.