Один из моих личных холмов, за который я готов умереть, - это возможность улучшить 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