Один из моих личных холмов, за который я готов умереть, - это возможность улучшить JavaScript, добавив улучшенную поддержку потоковой передачи. Пока что текущее состояние этой поддержки в значительной степени ограничено использованием WebWorkers, которые, к сожалению, не могут быть такими мощными, как потоки в таких языках, как C ++ или C #.
Однако я не хочу обвинять производителей браузеров, потому что эта тема довольно сложна и может быть сопряжена с большими трудностями.
При этом и при нынешнем способе работы в JavaScript мы все еще можем немного почувствовать, какой может быть многопоточность благодаря Promises (и асинхронным функциям).
Асинхронные звонки
Асинхронные вызовы на самом деле не новость для JavaScript. Каждый раз, когда у нас есть обратный вызов, мы можем считать, что используем некоторый асинхронный код. Подумайте, например, о любых вызовах XMLHttpRequest. Вызов сетевого ресурса займет время, и, следовательно, обратный вызов будет выполнен, когда данные будут готовы. Это заставляет ваш код больше не писать последовательным образом.
В Babylon.js мы инкапсулировали его в обратные вызовы, а также как, например, Конструктор текстуры, который принимает обратные вызовы onLoad и onError.
Обещания
Обещания - (и безусловно) одна из моих любимых функций, недавно добавленных в JavaScript.
Он определяет объект, который будет использоваться в качестве заполнителя для конечного результата (или ошибки) фрагмента асинхронного кода.
Поскольку он был отправлен в основные браузеры (см. Таблицу поддержки ниже), мы добавили много обещаний в Babylon.js, например, в класс SceneLoader.
Как видите, только Internet Explorer не поддерживает обещания, но мы вас охватили, и Babylon.js автоматически загрузит полифил обещаний, если он запущен в IE, поэтому вы можете уверенно использовать обещания все время.
Таким образом, этот код можно будет запускать везде:
Или, что еще лучше, теперь вы можете воспользоваться шаблоном async / await (но он больше не работает в IE):
Разве это не мило?
«Обещание» вашего кода
Если вы похожи на меня и любите использовать обещания (поскольку они делают код более чистым), вы найдете в движке места, где можно было бы использовать асинхронность, но для этого нет прямой функции.
Не проблема! Вы можете создавать свои собственные обещания и присоединяться к фантастическому миру асинхронного программирования.
Чтобы проиллюстрировать это, давайте возьмем пример, в котором вы хотите загрузить 2 текстуры и когда они загружаются (видите? Как только вы используете эту конструкцию «when something», вы знаете, что это хороший кандидат на обещание), мы хотели бы использовать их с материалом.
Итак, мы хотим создать функцию, которая будет возвращать обещание, и это обещание разрешится при загрузке обеих текстур. Что-то подобное:
Мы создаем и возвращаем обещание, но не разрешаем обещание (путем вызова метода resolve ()). Итак, в конечном итоге возникает вопрос: как я могу использовать обратные вызовы текстур, чтобы убедиться, что обе текстуры готовы?
Первым вариантом будет использование обратных вызовов текстуры onLoad, но я хотел бы использовать более общий подход (тот, который будет работать для текстур или чего-либо еще, основанного на Observables, который широко используется в Babylon.js).
Основная идея - полагаться на texture.onLoadObservable для уменьшения значения счетчика. Когда этот счетчик будет равен нулю, мы можем разрешить обещание:
Имея в виду эту функцию, вот наш окончательный код:
И теперь, когда у нас есть эта функция, убедиться, что две наши текстуры загружены, довольно просто и элегантно:
По умолчанию Babylon.js фактически предоставляет эту функцию WhenAllReady, но через обратный вызов, так что вот игровая площадка, где я трансформирую ее в обещание: https://www.babylonjs-playground.com/#XKSKJN
Идти дальше
Теперь, когда вы знаете, как создавать обещания, вы можете создавать более чистый код (точно меньше спагетти-кода!).
Не стесняйтесь, поделитесь тем, чем вы занимались, на нашем форуме!
Дэвид Дельтакош Катухе
https://www.twitter.com/deltakosh