В PlayCanvas при разработке игр или приложений важным этапом является загрузка различных ресурсов, таких как текстуры, модели, звуковые файлы и другие данные. Этот процесс требует тщательной обработки, чтобы обеспечить плавную работу приложения, избежать сбоев и задержек в интерфейсе. Для этого используются механизмы callbacks и Promise для асинхронной загрузки и обработки ресурсов. Разберём, как эффективно использовать эти подходы.
Callbacks — это функции, которые передаются в другие функции в качестве аргументов и вызываются по завершению какого-либо асинхронного процесса. В PlayCanvas этот механизм часто используется при загрузке ресурсов, когда необходимо выполнить некоторые действия после завершения загрузки файла.
Для загрузки ресурса с использованием callbacks в PlayCanvas
применяется метод load, который может принимать callback
функцию в качестве второго параметра. Это позволяет отложить выполнение
кода до тех пор, пока ресурс не будет загружен. Пример
использования:
var asset = new pc.Asset('myTexture', 'texture', {
url: 'path/to/texture.png'
});
asset.on('load', function() {
console.log('Texture loaded!');
// Здесь можно выполнить действия после загрузки
var texture = asset.resource;
material.diffuseMap = texture;
material.update();
});
app.assets.add(asset);
app.assets.load(asset);
В данном примере создаётся объект asset, который
представляет собой текстуру. С помощью метода on('load')
добавляется callback, который будет вызван после того, как текстура
полностью загрузится. Внутри этого callback можно работать с ресурсом,
например, назначить его на материал.
В случае ошибки загрузки также можно использовать callback:
asset.on('error', function(err) {
console.error('Error loading texture:', err);
});
Таким образом, использование callbacks позволяет контролировать порядок выполнения кода в асинхронной среде.
С появлением Promises в JavaScript был разработан более удобный способ работы с асинхронными операциями, что значительно улучшило читаемость и поддержку кода. PlayCanvas также поддерживает работу с Promise, что позволяет избежать “callback hell” — ситуации, когда множество вложенных callbacks затрудняет чтение и поддержку кода.
Для того чтобы использовать Promises при загрузке ресурсов, можно
создать обёртку над методом load. Вместо того, чтобы
передавать callback, мы возвращаем Promise, который разрешается
(resolve) при успешной загрузке и отклоняется (reject) при ошибке.
Пример:
function loadAsset(asset) {
return new Promise(function(resolve, reject) {
asset.on('load', function() {
resolve(asset.resource);
});
asset.on('error', function(err) {
reject(err);
});
app.assets.add(asset);
app.assets.load(asset);
});
}
var asset = new pc.Asset('myTexture', 'texture', {
url: 'path/to/texture.png'
});
loadAsset(asset)
.then(function(texture) {
console.log('Texture loaded!');
material.diffuseMap = texture;
material.update();
})
.catch(function(error) {
console.error('Error loading texture:', error);
});
Здесь создаётся функция loadAsset, которая возвращает
Promise. В случае успешной загрузки вызывается resolve(), и
ресурс передаётся в .then(). Если загрузка завершилась
ошибкой, вызывается reject(), и ошибка обрабатывается в
.catch().
Для загрузки нескольких ресурсов одновременно можно использовать
Promise.all. Это позволяет загрузить несколько ассетов, а
затем выполнить определённые действия после того, как все ресурсы будут
загружены. Пример:
var textureAsset = new pc.Asset('texture', 'texture', {
url: 'path/to/texture.png'
});
var modelAsset = new pc.Asset('model', 'model', {
url: 'path/to/model.json'
});
function loadAssets() {
return Promise.all([
loadAsset(textureAsset),
loadAsset(modelAsset)
]);
}
loadAssets()
.then(function(results) {
var texture = results[0];
var model = results[1];
console.log('All assets loaded!');
material.diffuseMap = texture;
material.update();
// Здесь можно работать с моделью
})
.catch(function(error) {
console.error('Error loading assets:', error);
});
Promise.all принимает массив из промисов и возвращает
новый промис, который будет разрешён только тогда, когда все промисы в
массиве будут выполнены успешно. Если хотя бы один из промисов
завершится с ошибкой, catch поймает ошибку и обработает
её.
Callbacks — это базовый механизм асинхронной обработки, но с ростом сложности кода может возникать ситуация, когда управление становится трудным, особенно когда несколько функций друг в друге вызываются последовательно. В таких случаях “callback hell” превращает код в трудночитаемый и труднопонимаемый. Также сложно обработать ошибки, так как их нужно обрабатывать в каждом callback.
Promises значительно упрощают работу с асинхронным
кодом, позволяют использовать методы .then(),
.catch(), .finally(), а также облегчают работу
с асинхронными операциями, которые нужно выполнить одновременно или
последовательно. Они предоставляют более чистый и современный способ
работы с асинхронными операциями.
Использование callbacks и Promise в PlayCanvas позволяет эффективно управлять загрузкой ассетов и их обработкой. Выбор между ними зависит от сложности приложения и предпочтений разработчика. В небольших проектах может быть достаточно использования callbacks, однако для более крупных и сложных проектов использование Promise предоставляет более удобный и читаемый способ работы с асинхронным кодом.