Thunkable X представлено несколько блоков для управления ходом исполнения программной логики и необходимо разобраться с тем, в каких случаях предпочтительнее использоваь тот или иной блок.
При помощи блока If происходит проверка присоединённой к нему переменной или выражения на предмет равенства значению true. Если выражение равно true, то происходит выполнение секции do. Если выражение равно false, то секция do не выполняется.
Справедливо ли утверждение того, что 10 > 3? Да. Текстовое поле отобразит строку ”Yes”.Выражение для проверки необязательно присоединять к самому блоку if. Его можно присвоить переменной, которую затем присоединить к блоку if.
У блока if есть две разновидности - if else, при помощи которой можно также задать ветвь для выполнения операций, если выражение ложно, а также If elseif, которое используется как оператор выбора одного действия из нескольких возможных (многовариантный выбор). Если вариантов выбора много, то работать с одним блоком if elseif неудобно по причине того, что окно для добавления новых ветвей будет отображается в самом низу блока, да и редактировать варианты в длинной вертикальной "расчёстке" непросто. В таких случаях лучше разбить один большой блок на большое количество блоков с одной веткой, вставив их в однократный блок цикла как будет показано позже.
В блоки if часто используются блоки операций сравнения – больше, меньше, равно, не равно и др. Для корректной работы сравнивать нужно данные одинакового типа. Если необходимо сравнить данные разных типов, то вначале их приводят к одному типу. Если одно выражение имеет строковый тип, а второе – числовой, то производится сравнение строк и нет ничего удивительного в том, что ”10age” > 5 = false. Строки сравниваются на основе лексикографического упорядочивания (сравниваются порядковые номера символов в таблице Юникода).
Циклический порядок выполнения блоков
Этот тип порядка выполнения блоков используется в том случае, когда происходит работа с коллекциями (наборами данных) или необходимо выполнить повторяющиеся действия, например, произвести поиск информации в базе данных, списке или в тексте, вывести маркеры на Google Map и др.
В отличие от линейного и разветвляющегося порядка, циклический является простейшим способом автоматизации, когда при помощи небольшого количества блоков можно выполнить огромное количество операций. Одно выполнение цикла называется итерацией.
Необходимо внимательно следить за использованием в циклах асинхронных блоков или вызовов, а также блоков, выполнение которых занимает очень много времени. Программисту кажется, что операции в цикле должны выполняться последовательно друг за другом, но нужно помнить о том, что и загрузка данных, и выполнение блоков происходит c какой-то задержкой и не может происходить моментально, о чём будет подробно рассказано на следующем уроке при изучении блоков. Циклы выполняются очень быстро, и может получиться так, что 100 итераций цикла уже прошли, а данные из Интернета ещё не поступили в блок, который был вызван в момент выполнения первой итерации.
Значит ли это то, что следует избегать использования асинхронных боков в циклах? Нет. Если окружение (контекст), в котором используются асинхронные блоки, не требуют последовательного выполнения действий, то можно смело использовать такие блоки. Напрмер, если необходимо просто создать 10 кнопок, то асинхронный блок можно напрямую использовать в цикле. Если же нужно создать 10 кнопок в определённом порядке, например, в ходе получения данных из AirTable или Firebase, то в этом случае нужно использовать рекурсивную функцию для синхронизации последовательного создания кнопок.
Запомните, если необходимо вызвать асинхронный блок более одного раза подряд и необходимо чтобы эти вызовы выполнялись строго друг за другом, то цикл необходимо заменить функцией, которая будет вызываться только после успешного выполнения предыдущего вызова. Иначе постоянно будут возникать ошибки.
Одна итерация цикла будет выполнена достаточно быстро даже при использовании “тяжелых блоков”, для выполнения которых требуется большое количество времени. Если же необходимо совершить несколько итераций, то падение скорости может быть весьма заметным. Насколько? Начиная от 10 и до нескольких тысяч раз.
В многопоточных средах для выполнения тяжелых задач создают отдельные потоки, но в Thunkable X вопросом повышения производительности платформы разработчики не занимались совсем, полагая, что пользователям гораздо важнее простота работы с этим инструментом. Это привело к большому количеству проблем, потому что пользователям нужны отзывчивые, а не медленно работающие приложения.
Для удобства работы с данными в Thinkable X используются следующие блоки циклов:
Цикл repeat
Это самый простой блок цикла, содержимое которого выполняется заданное число раз. Помимо всего прочего его можно использовать для замены одного большого оператора Ifelseif для более удобной работы.
Цикл сount
Это более сложный и универсальный цикл, в котором можно задать не только количество повторений, но и величину шага в параметре by, а также направление работы цикла в сторону увеличения переменной цикла или в сторону уменьшения, если число в параметре from больше числа в параметре to.
Данный цикл позволяет быстро изменить количество итераций. Например, вначале шаг был равен 1, но вам стало нужно увеличить количество итераций в 10 раз. Задайте величину шага равной 0,1. Количество итераций можно быстро поменять и в цикле repeat, но данный цикл позволяет использовать переменную цикла без необходимости создания для этого отдельной переменной, как это придётся сделать при использовании цикла repeat.
Учтите, переменная цикла является глобальной переменной и после выполнения цикла она будет иметь последнее присвоенное ей значение. Не используйте одинаковые имена переменных циклов, если они выполняются внутри друг друга. Это приведёт к ошибке, так как значение переменной внешнего цикла будет перезаписано внутри вложенного в него цикла.
Цикл foreach
Это цикл предназначен для работы со массивами объектов и коллекциями компонентов при использовании блоков Any. При работе этого цикла не используется индекс, потому что переменная цикла содержит ссылку на объект, и нет необходимости использовать блокдля для получения объекта из списка по индексу.
Циклы while и until
Это циклы с условиями, для работы которых необходимо задать условие.
Секция do цикла будет выполнена, если условие имеет значение true. Разница состоит в том, что в цикле while условие проверяется перед выполнением итерации, а в цикле until – после, то есть, сначала все блоки внутри цикла выполнятся и только после этого произойдёт проверка условия. По этой причине цикл until выполнится хотя бы один раз, тогда как цикл while может не выполниться ни разу.
Если вам нужно сделать так, чтобы цикл выполнился хотя бы один раз, то используйте цикл until.
Блок прерывания цикла breakout
Блок break out используется для оптимизации работы цикла и предотвращения выполнения им ненужных итераций.
Предположим, у нас есть какой-нибудь справочник, например, список, содержащий 20 тысяч названий городов с информацией о каждом из них. Для поиска в нём введённого пользователем города используется цикл по всем элементам списка. Предположим, искомый город имеет индекс 500. В цикле используется проверка на совпадение искомого города с текущим городом из списка. Если в блоке if нет блока break out, то после нахождения города цикл продолжит свою работу и бессмысленно выполнит ещё 19500 итераций. Во избежание этого в блок if необходимо добавить break out.
Блок break out также используется для выхода из бесконечно работающих циклов. Бесконечные циклы используются в случаях, когда условий выхода из цикла может быть несколько или по каким-то причинам удобнее задать условие выхода внутри итерации, а не перед ней или после неё.
Для создания бесконечного цикла можно использовать блоки со счётчиками repeat и count, присоединив к ним математический блок бесконечности, но профессиональные программисты для этого используют блок цикла while с присоединённым к нему блоком true.
Ресурсы приложения ограничены и работа бесконечного цикла быстро приведёт к зависанию приложения. Для дополнительной защиты от возникновения такой ситуации на этапе отладки приложения можно использовать переменную счётчик и проверку внутри цикла на превышение счётчиком заданного значения и выходом из него.
Блок break out прерывает работу только того чикла, в котором он находится. Если в приложении используется вложенный цикл, то для выхода из всех циклов в каждом из них нужно использовать блок break out.
Не стоит создавать большое количество вложенных друг в друга циклов. Это затруднит работу с такой конструкцией и поиск в ней ошибок. Одного или двух вложенных циклов будет достаточно для решения большинства задач.
Блок continue
Этот блок используется для прерывания выполнения текущей итерации и переходу к следующей.
Предположим, в блоке цикла находится 10 блоков, первые 5 из которых должны выполняться всегда, в оставшиеся 5, только при выполнении определённого условия. Последние блоки можно поместить в блок if, но использование блока continue упрощает вид блоков и всю дальнейшую работу с ними, включая поиск ошибок..
Если вам нужно произвести фильтрацию списка по множеству полей и отобрать из него только те элементы, которые соответствуют всем условиям поиска, то вместо одного большого и неудобного блока if используйте много коротких блоков if с блоком continue
Алгоритм работы очень прост. Если по какому-то полю нет совпадения, то происходит переход к следующей итерации.
Использование циклов на практике
Сложность использования циклов состоит в том, что они выполняются очень быстро и в случае возникновения ошибки либо внутри него, либо после его успешного завершения трудно понять, какой блок внутри цикла вызвал ошибку. Для поиска источника ошибки можно либо выводить промежуточные результаты работы цикла в область отображения списка, либо использовать диалог Alert. В последнем случае нужно быть очень аккуратными. Диалог Alert не останавливает работу цикла, и может получиться так, что он будет отображен столько раз, сколько итераций выполнит цикл. После этого придётся либо очень долго закрывать все диалоги Alert, либо завершить работу приложения.
Одна из часто встречающихся ошибок – использование цикла для получения данных из AirTable и Firebase. Они создают цикл, в тело которого добавляются блоки для получения значений из строки или ячейки. После безуспешных попыток получить правильные данные они задают вопрос на форуме, где им советуют использовать блок задержки, после чего пользователи радуются тому, что всё заработало. Но это не так. Если у других пользователей скорость соединения с Интернетом низкая, то выбранной задержки может не хватить для получения данных, и он получит ошибочный результат. Надёжное решение состоит в замене многократных облачных вызовов получением данных из локального списка. Для этого нужно загрузить все необходимые данные в список приложения, а затем в цикле по этому локальному списку выбирать нужные данные. Но это же приведёт к многократной загрузке избыточных данных, если данные в AirTable постоянно обновляются! Да, но в таком случае нужно использовать Firebase, потому что AirTable не предназначен для оперативного обмена данными.
Циклы предназначены для работы в локальной синхронной среде, а web-среда, как мы знаем, является удалённой асинхронной средой. Попытка работать с ней, как с локальным массивом или списком данных ни к чему хорошему не приведёт. Это всё равно, что отправить по почте письмо с надеждой на то, что ответ поступит так же быстро, как и по электронной почте.
Быстрее всего работают циклы repeat. Далее идёт цикл repeat while и count width. Медленнее всех выполняется цикл for each item. В реальных приложениях он может выполняться раз в 10 медленнее цикла repeat уже при 10 тыс. итераций.