Udostępnij za pośrednictwem


Optymalizacja kodu

Ponieważ aplikacje oparte na kanwie ewoluują, aby sprostać różnorodnym wymaganiom biznesowym, wyzwaniem staje się utrzymanie optymalnej wydajności. Zawiłości związane z obsługą danych, projektowaniem interfejsu użytkownika i funkcjonalnością aplikacji opartych na kanwie wymagają zniuansowanego podejścia do optymalizacji kodu.

W miarę jak aplikacje oparte na kanwie stają się coraz bardziej skomplikowane, deweloperzy napotykają wyzwania związane z wyszukiwaniem danych, złożonością formuł i szybkością renderowania. Potrzeba znalezienia równowagi między solidną funkcjonalnością a responsywnymi interfejsami użytkownika podkreśla znaczenie przyjęcia systematycznego podejścia do optymalizacji kodu.

Optymalizacja formuł Power Fx

Funkcja With

Funkcja With ocenia formułę dla pojedynczego rekordu. Formuła może obliczać wartość i/lub wykonywać akcje, takie jak modyfikowanie danych lub współdziałanie z połączeniem. Użyj With, aby poprawić czytelność złożonych formuł, dzieląc je na mniejsze nazwane podformuły. Te nazwane wartości działają tak samo, jak proste zmienne lokalne, które są ograniczone do zakresu With. Użycie opcji With jest preferowane w stosunku do zmiennych kontekstowych lub globalnych, ponieważ jest to samodzielna, łatwa do zrozumienia i może być używana w dowolnym kontekście formuł deklaracyjnych. Dowiedz się więcej o funkcji With.

Zrzut ekranu formuły Power Fx wykorzystującej funkcję With

Funkcja Concurrent

Funkcja Concurrent pozwala na jednoczesną ocenę wielu formuł określonych w tej samej właściwości, jeśli mają one łącznik lub wywołania Dataverse. Zwykle wiele formuł oblicza się, łącząc je ze sobą za pomocą operatora ; (średnik), który ocenia każdą formułę sekwencyjnie. Dzięki funkcji Concurrent, aplikacja oceni wszystkie formuły w obrębie właściwości jednocześnie, nawet po użyciu operatora ;. Ta współbieżność pomaga użytkownikom czekać krócej na ten sam wynik. Jeśli kolejne wywołania danych nie są uruchamiane przed zakończeniem poprzednich, aplikacja musi czekać przez czas będący sumą czasów wszystkich żądań. Jeśli wywołania danych są uruchamiane jednocześnie, czas oczekiwania aplikacji zostanie skrócony do najdłużej wykonywanego żądania. Dowiedz się więcej o Concurrent tej funkcji.

Concurrent(
    ClearCollect(colAccounts1, Accounts),
    ClearCollect(colUsers1, Users),
    ClearCollect(colEnvDef1, 'Environment Variable Definitions'),
    ClearCollect(colEnvVal1, 'Environment Variable Values')
);

Funkcja Coalesce

Funkcja Coalesce ocenia kolejno swoje argumenty i zwraca pierwszą wartość, która nie jest pusta lub pusty ciąg. Tej funkcji należy użyć do zastąpienia pustej wartości lub pustego ciągu innym ciągiem, ale pozostawienia niepustych i wypełnionych wartości ciągów bez zmian. Jeśli wszystkie argumenty są puste lub puste, funkcja zwraca wartość pustą, dzięki czemu Coalesce pustych ciągów na puste wartości jest dobrym sposobem na konwersję pustych ciągów.

Na przykład:

If(Not IsBlank(value1), value1, Not IsBlank(value2), value2)

Wymaga dwukrotnej oceny wartości 1 i wartości 2. Funkcję tę można sprowadzić do:

Coalesce(value1, value2)

Funkcja IsMatch

Funkcja IsMatch sprawdza, czy ciąg tekstowy jest zgodny ze wzorcem, który może zawierać znaki zwykłe, wstępnie zdefiniowane wzorce lub wyrażenie regularne. Dowiedz się więcej o funkcji IsMatch.

Na przykład ta formuła pasuje do amerykańskiego numeru ubezpieczenia społecznego:

IsMatch(TextInput1.Text, "\d{3}-\d{2}-\d{4}")

Wyjaśnienie wyrażenia regularnego:

\\d dopasowuje dowolną cyfrę (0-9).

{3} Określa, że poprzedzający wzorzec cyfr (\d) powinien wystąpić dokładnie trzy razy.

- dopasowuje znak myślnika.

{2} Określa, że poprzedzający wzorzec cyfr (\2d) powinien wystąpić dokładnie 2 razy.

{4} Określa, że poprzedzający wzorzec cyfr (\2d) powinien wystąpić dokładnie 4 razy.

Więcej przykładów IsMatch:

IsMatch(TextInput1.Text, "Hello World")
IsMatch(TextInput1\_2.Text, "(?!^\[0-9\]\\\*$)(?!^\[a-zA-Z\]\\\*$)(\[a-zA-Z0-9\]{8,10})")

Optymalizacja aplikacji OnStart

Właściwość OnStart dla aplikacji kanwy odgrywa kluczową rolę w definiowaniu działań, które mają miejsce po uruchomieniu aplikacji. Ta właściwość pozwala twórcom aplikacji na wykonywanie globalnych zadań inicjalizacyjnych, konfigurowanie zmiennych i wykonywanie działań, które powinny być wykonywane tylko raz podczas procesu uruchamiania aplikacji. Zrozumienie i efektywne wykorzystanie właściwości OnStart jest niezbędne do tworzenia responsywnych i wydajnych aplikacji opartych na kanwie.

Zalecanym podejściem jest usprawnienie funkcji App.OnStart poprzez migrację ustawień zmiennych do nazwanych formuł. Nazwane formuły, zwłaszcza te skonfigurowane na wczesnym etapie cyklu życia aplikacji, okazują się korzystne. Formuły te obsługują inicjalizację zmiennych na podstawie wywołań danych, zapewniając czystszą i bardziej zorganizowaną strukturę kodu. Więcej szczegółów Buduj duże i złożone aplikacje oparte na kanwie - Power Apps | Microsoft Learn.

Uwaga

Właściwość OnStart jest konieczna. Jest to uporządkowana lista prac, które należy wykonać przed wyświetleniem pierwszego ekranu. Ponieważ jest tak szczegółowy nie tylko w kwestii co należy zrobić, ale także kiedy to zadanie musi zostać wykonane w oparciu o kolejność, ogranicza to zmianę kolejności i odraczanie optymalizacji, które w przeciwnym razie mogłyby zostać wykonane.

Ekran startowy

Jeśli App.OnStart zawiera wywołanie funkcji Navigate, nawet jeśli znajduje się ona w funkcji If i jest rzadko wywoływana, musimy zakończyć wykonywanie App.OnStart przed wyświetleniem pierwszego ekranu aplikacji. App.StartScreen to nowy deklaratywny sposób wskazywania, który ekran powinien zostać wyświetlony jako pierwszy, który nie blokuje optymalizacji.

Ustawienie właściwości StartScreen pokazuje pierwszy ekran przed zakończeniem App.OnStart. App.StartScreen declares który obiekt ekranu ma zostać wyświetlony jako pierwszy, bez konieczności wstępnego przetwarzania.

Zamiast pisać kod typu:

App.OnStart = Collect(OrdersCache, Orders);
If(Param("AdminMode") = "1", Navigate(AdminScreen), Navigate(HomeScreen))

Zmień kod na:

App.OnStart = Collect(OrdersCache, Orders);
App.StartScreen = If(Param("AdminMode") = "1", AdminScreen, HomeScreen)

Więcej informacji można znaleźć na stronie <https://Power Apps.microsoft.com/en-us/blog/app-startscreen-a-new-declarative-alternative-to-navigate-in-app-onstart/>.

Ostrzeżenie

Unikaj zależności pomiędzy StartScreen i OnStart. Odwoływanie się do nazwanej formuły, która z kolei odwołuje się do zmiennej globalnej, może powodować warunek wyścigu, w którym StartScreen nie jest poprawnie stosowany. Uwaga: nie powinniśmy mieć zależności między wartością StartScreen a OnStart. Blokujemy odwoływanie się do zmiennych globalnych w StartScreen, ale możemy odwołać się do nazwanej formuły, która z kolei odwołuje się do zmiennej globalnej, a to może spowodować warunek wyścigu, w którym StartScreen nie zostanie zastosowany poprawnie.

Nazwane formuły

Nazwane formuły są statyczne lub stałe, które można zdefiniować w sekcji App.Formulas. Raz zadeklarowane w App.Formulas, mogą być używane w dowolnym miejscu w aplikacji, a ich wartość zawsze pozostaje aktualna. Nazwane formuły w Power Apps umożliwiają definiowanie wartości lub zestawów wartości, które są automatycznie zarządzane i aktualizowane przez platformę. Ta funkcjonalność przenosi odpowiedzialność za obliczanie wartości i utrzymanie z dewelopera na Power Apps, usprawniając proces rozwoju. Nazwane formuły w Power Apps to potężna funkcjonalność, która może znacznie zwiększyć wydajność i łatwość konserwacji aplikacji.

Nazwane formuły mogą również służyć do deklarowania motywów aplikacji. W wielu przypadkach, gdy tworzone są aplikacje korporacyjne, chcemy, aby aplikacja miała wspólne motywy, aby zapewnić spójny wygląd i wrażenia użytkownika. Aby utworzyć motyw, istnieje 10 lub 100 zmiennych, które należy zadeklarować w App OnStart. Zwiększyło to długość kodu i czas inicjalizacji aplikacji.

Nowoczesne kontrolki mogą również znacznie pomóc w tworzeniu motywów i zredukować logikę napisaną przez klienta do obsługi motywów. Nowoczesne sterowanie jest obecnie w wersji zapoznawczej.

Na przykład, poniższy kod w App.OnStart można przenieść do App.Formulas, skracając w ten sposób czas uruchamiania na deklaracjach zmiennych globalnych.

Set(BoardDark, RGBA(181,136,99, 1));
Set(BoardSelect, RGBA(34,177,76,1));
Set(BoardRowWidth, 10);                      // expected 8 plus two guard characters for regular expressions.
Set(BoardMetadata, 8 \* BoardRowWidth + 1);   // which player is next, have pieces moved for castling rules, etc.
Set(BoardBlank, "----------------------------------------------------------------\_00000000000000");
Set(BoardClassic, "RNBQKBNR\_\_PPPPPPPP------------------------\_--------\_\_pppppppp\_\_rnbqkbnr\_\_0000000000");

Kod można przenieść do App.Formulas w następujący sposób:

BoardSize = 70;
BoardLight = RGBA(240,217,181, 1);
BoardDark = RGBA(181,136,99, 1);
BoardSelect = RGBA(34,177,76,1);
BoardRowWidth = 10;                      // expected 8 plus two guard characters for regular expressions
BoardMetadata = 8 \* BoardRowWidth + 1;   // which player is next, have pieces moved for castling rules, etc.
BoardBlank = "----------------------------------------------------------------\_00000000000000";
BoardClassic = "RNBQKBNR\_\_PPPPPPPP------------------------\_--------\_\_pppppppp\_\_rnbqkbnr\_\_0000000000";

Innym przykładem jest ustawienie zajazdu Lookups. W tym przypadku wymagana jest zmiana w formule Lookup, aby uzyskać informacje o użytkowniku z Office 365, zamiast Dataverse. Jest tylko jedno miejsce, w którym zmiana jest wymagana bez zmiany kodu wszędzie.

UserEmail = User().Email;
UserInfo = LookUp(Users, 'Primary Email' = User().Email);
UserTitle = UserInfo.Title;
UserPhone = Switch(UserInfo.'Preferred Phone', 'Preferred Phone (Users)'.'Mobile Phone', UserInfo.'Mobile Phone',
UserInfo.'Main Phone');

Formuły te ucieleśniają istotę obliczeń. Opisują one proces określania UserEmail, UserInfo, UserTitle i UserPhone na podstawie innych wartości. Ta logika jest hermetyzowana, umożliwiając szerokie wykorzystanie w całej aplikacji i może być modyfikowana w jednym miejscu. Zdolność adaptacji rozciąga się na przełączanie z tabeli Dataverse Users na łącznik Office 365 bez konieczności wprowadzania zmian w formułach rozproszonych w całej aplikacji.

Innym podejściem jest optymalizacja countRows.

varListItems = CountRows(SampleList)

W przypadku funkcji Set, zmienna varListItems będzie musiała zostać zainicjowana początkową liczbą wierszy na przykładowej liście i ustawiona ponownie po dodaniu lub usunięciu produktów z listy. W przypadku formuł nazwanych, gdy dane ulegają zmianie, zmienne varListitems są aktualizowane automatycznie.

Nazwane formuły we właściwości App.Formulas zapewniają bardziej elastyczne i deklaratywne podejście do zarządzania wartościami i obliczeniami w całej aplikacji, oferując korzyści w zakresie niezależności czasowej, automatycznych aktualizacji, łatwości konserwacji i niezmiennych definicji w porównaniu do polegania wyłącznie na App.OnStart.

Aspect Nazwane formuły (App.Formulas) App.OnStart
Niezależność czasowa Formuły są dostępne natychmiast, mogą być obliczane w dowolnej kolejności. Zmienne mogą wprowadzać zależności czasowe, wpływając na dostępność.
Automatyczne aktualizacje Formuły są automatycznie aktualizowane, gdy zmieniają się zależności. Zmienne są ustawiane raz podczas uruchamiania; mogą być potrzebne ręczne aktualizacje.
Możliwość konserwacji Scentralizowane formuły w jednej lokalizacji poprawiają łatwość konserwacji. Rozproszone zmienne mogą wymagać znalezienia i aktualizacji w wielu miejscach.
Niezmienialne definicje Definicje formuł w App.Formulas są niezmienne. Zmienne wartości mogą być podatne na przypadkowe zmiany.

Funkcje zdefiniowane przez użytkownika

User Defined Functions to eksperymentalna funkcjonalność w Power Apps Authoring Studio, która umożliwia użytkownikom tworzenie własnych niestandardowych funkcji.

Aby skorzystać z tej funkcji, w sekcji Ustawienia eksperymentalne wybierz opcję Nowy silnik analizy i Funkcja zdefiniowana przez użytkownika (UDF)

Zdefiniuj formułę w App.Formulas w następujący sposób:

FunctionName(Parameter1:DataType1, Parameter2:DataType2):OutputDataType = Formula

Kod działa tak:

  • FunctionName jest używana do wywołania funkcji

  • Parameter jest nazwą wejścia. Dozwolone jest jedno lub więcej wejść

  • DataType jest argumentem przekazywanym do funkcji, musi odpowiadać temu typowi danych. Dostępne typy danych to Boolean, Color, Date, Datetime, GUID, Hyperlink, Text, Time, Untyped Object

  • OutputDataType jest typem danych, w którym będzie zapisane wyjście funkcji

  • Formula jest wyjściem funkcji

// Function to calculate the area of a circle based on the radius
calcAreaOfCircle(radius: Number): Number = 
    IfError(Pi() * radius * radius, 0);

Użyj IfError, aby zaimplementować obsługę błędów w zdefiniowanej funkcji.

Wywołanie zdefiniowanej funkcji z kontrolki tekstu/etykiety.

calcAreaOfCircle(Int(*TextInput1*.Text))

Uwaga

Jest to funkcja eksperymentalna i może ulec zmianie. Niektóre typy danych, takie jak rekordy i filtry, nie są jeszcze obsługiwane.

Optymalizacja zmiennych

Zmienne są używane do definiowania i ustawiania lokalnych i globalnych wartości, które mogą być używane wszędzie w aplikacjach. Chociaż są wygodne, zbyt wiele z nich może spowodować, że aplikacja będzie mniej zoptymalizowana.

Poniższy przykład demonstruje ustawienie zmiennej dla każdego atrybutu obiektu, co wymaga użycia Set dla każdej właściwości.

Set(varEmpName, Office365Users.MyProfile().DisplayName);
Set(varEmpCity, Office365Users.MyProfile().City);
Set(varEmpPhone, Office365Users.MyProfile().BusinessPhones);
Set(varEmpUPN, Office365Users.MyProfile().UserPrincipalName);
Set(varEmpMgrName, Office365Users.ManagerV2(varEmpUPN).DisplayName);

Bardziej zoptymalizowanym podejściem jest korzystanie z nieruchomości wtedy, gdy jest ona potrzebna:

Set(varEmployee, Office365Users.MyProfile())
"Welcome " & varEmployee.DisplayName

Mądrze używaj zmiennych kontekstowych i globalnych. Jeśli zakres zmiennej wykracza poza pojedynczy ekran, należy rozważyć użycie zmiennych globalnych zamiast zmiennych kontekstowych.

Zbyt wiele nieużywanych zmiennych przyczynia się do zwiększonego zużycia pamięci i nieco wolniejszej inicjalizacji aplikacji. Dzieje się tak, ponieważ zasoby są przydzielane dla tych zmiennych, nawet jeśli nie są one aktywnie używane. Zbyt wiele nieużywanych zmiennych może również prowadzić do ogólnej złożoności logiki aplikacji. Chociaż wpływ nieużywanych zmiennych może nie być poważny, dobrą praktyką jest utrzymywanie czystej i dobrze zorganizowanej aplikacji Power App w celu zapewnienia optymalnej wydajności i łatwości rozwoju.

Optymalizowanie kolekcji

Kolekcje to tymczasowe struktury przechowywania danych, które mogą być używane do przechowywania i manipulowania danymi w aplikacji Power Apps. Istnieje jednak cienka granica, kiedy kolekcje mogą prowadzić do zwiększenia wydajności. W związku z tym należy ograniczyć korzystanie z kolekcji. Staraj się używać ich tylko wtedy, gdy jest to konieczne.

// Use this pattern
ClearCollect(colErrors, {Text: gblErrorText, Code: gblErrorCode});

// Do not use this pattern
Clear(colErrors);
Collect(colErrors, {Text: gblErrorText, Code: gblErrorCode});

Aby policzyć rekordy w lokalnej kolekcji, użyj CountIf zamiast Count(Filter()).

Weź pod uwagę te wskazówki podczas pracy z kolekcjami:

Ograniczenie rozmiaru i liczby kolekcji. Ponieważ kolekcje mają lokalizację lokalną dla aplikacji, są one przechowywane w pamięci urządzenia przenośnego. Im więcej danych przechowują kolekcje lub im większa jest ich liczba, tym gorsza jest wydajność. Użyj funkcji ShowColumns, aby uzyskać tylko określone kolumny. Dodaj funkcję Filter, aby uzyskać tylko odpowiednie dane.

Poniższa przykładowa funkcja zwraca cały zestaw danych.

ClearCollect(colDemoAccount, Accounts);

Porównaj z poniższym kodem, który zwróci tylko określone rekordy i kolumny:

ClearCollect(colAcc,
              ShowColumns(
                Filter(Accounts, !IsBlank('Address 1: City')),
                "name","address1_city"))

Przykładowy kod zwraca ten zestaw danych:

Zrzut ekranu zbioru danych z tabelą o nazwie colAcc i dwiema kolumnami z danymi, address1_city i name

Ustawienie częstotliwości odświeżania źródła danych. Jeśli dodajesz nowe rekordy do kolekcji, musisz ją odświeżyć lub pobrać do niej, aby nowe lub zmienione rekordy znalazły się w kolekcji. Jeśli źródło danych jest aktualizowane przez wielu użytkowników, należy odświeżyć kolekcję, aby uzyskać nowe lub zmienione rekordy. Więcej wywołań odświeżania oznacza więcej interakcji z serwerem.

Buforowanie danych w kolekcjach i zmiennych

Kolekcja, zasadniczo zmienna tabelaryczna, różni się tym, że przechowuje wiersze i kolumny danych, a nie pojedynczy produkt danych. Ich użyteczność polega na dwóch głównych celach: po pierwsze, do agregowania danych przed przesłaniem ich do źródła danych, a po drugie, do buforowania informacji, eliminując potrzebę częstych zapytań do źródła danych. Ponieważ kolekcje są zgodne z tabelaryczną strukturą zarówno źródła danych, jak i Power Apps, oferują one wydajny sposób interakcji z danymi, nawet w scenariuszach offline.

// Clear the contents of EmployeeCollection, it already contains data
ClearCollect(
    colEmployee,
    {
        Id: "1",
        Name: "John",
        Department: "IT"
    },
    {
        Id: "2",
        Name: "Nestor",
        Department: "IT"
    }
)

Usuwanie nieużywanych zmiennych i mediów

Chociaż nieużywane nośniki i zmienne mogą nie mieć drastycznego wpływu na wydajność aplikacji, ważne jest, aby oczyścić aplikację z wszelkich nieużywanych nośników lub zmiennych.

  • Nieużywane pliki multimedialne przyczyniają się do ogólnego wzrostu rozmiaru aplikacji. Może to prowadzić do wolniejszego ładowania aplikacji.

  • Wiele nieużywanych zmiennych przyczynia się do zwiększonego zużycia pamięci i nieco wolniejszej inicjalizacji aplikacji. Dzieje się tak, ponieważ zasoby są przydzielane dla tych zmiennych, nawet jeśli nie są one aktywnie używane. Dodatkowo zbyt wiele nieużywanych zmiennych może prowadzić do ogólnej złożoności logiki aplikacji.

  • Użyj App Checker, aby sprawdzić nieużywane nośniki i zmienne.

Optymalizacja ekranów i elementów sterujących

Unikanie odwołań do elementów sterujących

Elementy sterujące, które odwołują się do elementów sterujących na innych ekranach, mogą spowolnić ładowanie aplikacji i nawigację. Może to zmusić aplikację do natychmiastowego załadowania innych ekranów, zamiast czekać, aż użytkownik przejdzie do tego ekranu. Aby rozwiązać ten problem, zamiast tego użyj zmiennych, kolekcji i kontekstu nawigacji do współdzielenia stanu między ekranami.

Narzędzie do sprawdzania aplikacji w studiu autorskim Power Apps App Checker, pokazuje kontrolki, które są wzajemnie powiązane. Regularnie sprawdź App Checker, aby rozwiązać ten problem.

Oto przykład kontrolek z odsyłaczami. Na poniższym obrazku kontrolka Gallery 1 jest powiązana z kontrolką Screen 2, Label 2.

Zrzut ekranu z Power Apps Studio przedstawiający kontrolkę z odsyłaczami

Jeśli odwołasz się do kontrolki z pierwszego ekranu w aplikacji na drugim ekranie, nie będzie to miało wpływu na wydajność, ponieważ pierwszy ekran został już załadowany, co może być dobrą rzeczą, ponieważ aplikacja deklaruje zamiast używać zmiennych.

Jeśli odwołujesz się do kontrolek, które nie zostały jeszcze załadowane, np. pierwszy ekran odwołujący się do kontrolki o nazwie Label 3 z ekranu 3, będzie wymagał załadowania ekranu do pamięci.

Włącz DelayOutput dla kontrolek tekstowych

Ustawienie opóźnienia wyjścia Gdy ustawione na true, wejście użytkownika jest rejestrowane z półsekundowym opóźnieniem. Jest to przydatne do opóźniania kosztownych operacji (np. do filtrowania, gdy dane wejściowe są używane w innych formułach) do czasu zakończenia wprowadzania tekstu przez użytkownika.

Na przykład dla Galerii, której produkty są filtrowane w zależności od tego, co jest wprowadzane do kontrolki TextInput:

  • Przy ustawieniu DelayOutput na false, co jest wartością domyślną, galeria jest filtrowana natychmiast po wpisaniu dowolnego tekstu. Jeśli masz galerię z dużą ilością produktów, przeładowanie galerii zmianami od razu spowalnia wydajność; korzystniej byłoby trochę poczekać. Jest to praktyczne, gdy używasz TextInput do wyszukiwania ciągu znaków (patrz  Wyszukaj lub nowe funkcje StartsWith).

  • Po ustawieniu DelayOutput na wartość true, zmiany są wykrywane z sekundowym opóźnieniem. Ma to na celu zapewnienie czasu na dokończenie wpisywania żądanej treści. Opóźnienie działa dobrze, gdy jest używane do wspomagania właściwości TextInput.OnChange. Jeśli masz akcje powiązane ze zmianami, nie chcesz, aby były one uruchamiane, dopóki wszystko, co chcesz, nie zostanie wpisane w polu.

Delegowanie i przetwarzanie po stronie serwera

Delegowanie

Delegowanie w Power Apps to koncepcja, która odnosi się do zdolności aplikacji do odciążania niektórych operacji do bazowego źródła danych zamiast przetwarzania operacji w samej aplikacji Power Apps. Korzystając z delegowania w Power Apps, programiści mogą tworzyć bardziej wydajne i skalowalne aplikacje, które działają dobrze nawet w scenariuszach obejmujących duże zbiory danych. Ważne jest, aby zdawać sobie sprawę z ograniczeń delegacji dla określonych źródeł danych i operacji oraz odpowiednio projektować aplikacje, aby osiągnąć optymalną wydajność.

![UWAGA] Nie wszystkie funkcje można delegować. Aby dowiedzieć się więcej o delegowaniu uprawnień, zapoznaj się z Zrozumienie delegowania.

Delegowanie ma kilka zalet, takich jak optymalizacja zapytań i dodaje obsługę dużych zbiorów danych. Ponadto, jeśli dane źródłowe często się zmieniają, delegowanie pomaga zachować aktualność danych.

Redukcja wywołań API do źródła danych

Czasami wygodne może być po prostu przestrzeganie praktyk kodowania, takich jak tworzenie kolekcji poprzez wykonywanie złączeń w aplikacji opartej na kanwie. Patrz poniższy kod:

W tym przykładzie istnieją dwie tabele: Kierowcy i Ciężarówki. Deweloper pisze kod, aby utworzyć kolekcję kierowców i szczegółów ciężarówki, a dla każdej ciężarówki dzwoni do kierowców, którzy są właścicielami ciężarówek.

// Bad code
ClearCollect(vartruckdata, AddColumns('Truck Details',
    "CITY",LookUp(Drivers, 'Truck Details'\[@'Dummy ID'\] = Drivers\[@'Truck Details'\],City),
        "FIRSTNAME",LookUp(Drivers, 'Truck Details'\[@'Dummy ID'\] = Drivers\[@'Truck Details'\],'Driver First Name'),
    "LASTNAME",LookUp(Drivers, 'Truck Details'\[@'Dummy ID'\] = Drivers\[@'Truck Details'\],'Driver Last Name'),
        "STATE",LookUp(Drivers, 'Truck Details'\[@'Dummy ID'\] = Drivers\[@'Truck Details'\],State)));

Wykonywanie takich operacji łączenia z poziomu aplikacji opartej na kanwie może generować wiele wywołań do źródła danych, co prowadzi do bardzo wolnych czasów ładowania.

Lepszym podejściem jest:

// Good code
Set(
    varTruckData,
    LookUp(
        Drivers,
        'Dummy ID' = ThisRecord.'Dummy ID',
        'Driver First Name'
    ) & LookUp(
        Drivers,
        'Dummy ID' = ThisRecord.'Dummy ID',
        'Driver Last Name'
        )
);

Set(
    varTruckData,
    With(
        {
            vDriver: LookUp(
                Drivers,
                'Dummy ID' = ThisRecord.'Dummy ID'
            )
        },
        vDriver.'Driver First Name' & vDriver.'Driver Last Name'
    )
)

W scenariuszu czasu rzeczywistego możliwe jest skrócenie czasu ładowania z 5 minut do mniej niż 10 sekund poprzez poprawienie danych na poziomie źródła danych.

Przetwarzanie po stronie serwera

Różne źródła danych, takie jak SQL i Dataverse, umożliwiają delegowanie przetwarzania danych, takich jak filtrowanie i wyszukiwanie, do źródła danych. W SQL Server użytkownicy mogą tworzyć widoki, które mają treść zdefiniowaną przez zapytanie. Podobnie, dzięki Dataverse użytkownicy mogą tworzyć wtyczki o niskim kodzie, aby pisać logikę przetwarzania danych po stronie serwera i uzyskiwać ostateczne wyniki tylko w aplikacjach opartych na kanwie.

Delegowanie przetwarzania danych do serwera może poprawić ogólną wydajność, zmniejszyć ilość kodu po stronie klienta i jest łatwe w utrzymaniu.

Dowiedz się więcej o wtyczki w Dataverse.

Optymalizacja wzorców danych zapytań

Używanie opcji Jawny wybór kolumny

Funkcja jawnego wyboru kolumny (ECS) jest domyślnie włączona dla wszystkich nowych aplikacji. Jeśli nie jest ona włączona w Twojej aplikacji, należy ją włączyć. ECS automatycznie redukuje liczbę pobieranych kolumn do tych, które są używane w aplikacji. Jeśli funkcja ECS nie jest włączona, możesz pobierać więcej danych, niż potrzebujesz, co może mieć wpływ na wydajność. Czasami, gdy aplikacja pobiera dane z kolekcji, może zostać utracone pierwotne pochodzenie lub źródło kolumny. Nie wiemy, czy jest używany i upuszczamy go za pomocą ECS. Zazwyczaj można zmusić ECS do pracy dla brakującej kolumny poprzez użycie wyrażenia PowerFx ShowColumns a po odwołaniu do kolekcji lub poprzez użycie go w kontrolce.

Unikanie wywoływania Power Automate w celu wypełnienia kolekcji

Powszechną praktyką jest używanie Power Automate do pobierania i wypełniania kolekcji w Power Apps. Choć podejście to jest godne weryfikacji, istnieją sytuacje, w których może ono nie być najskuteczniejszym wyborem. Wywołanie Power Automate wiąże się z narzutem opóźnienia sieciowego i dodaje 0,6-sekundowy koszt wydajności do wywołania przepływu Power Automate.

Nadużywanie przepływów Power Automate może również prowadzić do limitów wykonania i dławienia. Dlatego zawsze należy oceniać kompromisy między opóźnieniem sieci a kosztami wydajności.

Wyeliminowanie problemu N+1

Problem N+1 jest częstym problemem w zapytaniach do baz danych, w których zamiast pobierać wszystkie wymagane dane w jednym zapytaniu, wykonywanych jest wiele dodatkowych zapytań w celu pobrania powiązanych danych. Może to prowadzić do problemów z wydajnością, ponieważ każde dodatkowe zapytanie wiąże się z dodatkowymi kosztami.

Proste wywołanie takie jak to w celu załadowania kolekcji może wygenerować N+1 wywołań do źródła danych.

ClearCollect(MyCollection, OrdersList,
    {
        LookUp(CustomersList,CustomerID = OrdersList[@CustomerID])
    }
)

W kontekście aplikacji opartych na kanwie i galerii, problem N+1 może pojawić się podczas pracy ze źródłami danych i galeriami, które wyświetlają powiązane rekordy. Problem pojawia się zazwyczaj, gdy wykonywanych jest więcej zapytań dla każdego produktu wyświetlanego w galerii, co prowadzi do wąskiego gardła wydajności.

Użyj obiektów widoku w SQL Server, aby uniknąć problemu z zapytaniami N+1 lub zmień interfejs użytkownika, aby uniknąć wyzwalania scenariusza N+1.

Dataverse automatycznie pobiera wymagane dane z powiązanych tabel i można wybrać kolumny z powiązanych tabel.

ThisItem.Account.'Account Name'

Jeśli rozmiar RelatedDataSourc jest niewielki (<500 rekordów), można buforować go w kolekcji i użyć kolekcji do obsługi scenariusza zapytania Lookup (N+1).

Ograniczenie rozmiaru pakietu

Chociaż Power Apps robi wiele, aby zoptymalizować ładowanie aplikacji, możesz podjąć kroki, aby zmniejszyć ślad swoich aplikacji. Zmniejszony ślad jest szczególnie ważny dla użytkowników starszych urządzeń lub użytkowników w lokalizacjach, w których występują większe opóźnienia lub ograniczona przepustowość.

  • Oceń multimedia osadzone w aplikacji. Jeśli coś nie jest używane, usuń to.

  • Osadzone obrazy mogą być zbyt duże. Zamiast plików PNG można użyć obrazów SVG. Należy jednak uważać na używanie tekstu w obrazach SVG, ponieważ używana czcionka musi być zainstalowana na kliencie. Świetnym rozwiązaniem, gdy trzeba wyświetlić tekst, jest nałożenie etykiety tekstowej na obraz.

  • Oceń, czy rozdzielczość jest odpowiednia dla danej obudowy. Rozdzielczość aplikacji mobilnej nie musi być tak wysoka, jak rozdzielczość aplikacji desktopowej. Eksperymentuj, aby uzyskać odpowiednią równowagę między jakością i rozmiarem obrazu.

  • Jeśli masz nieużywane ekrany, usuń je. Uważaj, aby nie usunąć żadnych ukrytych ekranów, z których korzystają tylko twórcy aplikacji lub administratorzy.

  • Oceń, czy nie próbujesz zmieścić zbyt wielu procesów w jednej aplikacji. Na przykład, czy w tej samej aplikacji znajdują się zarówno ekrany administratora, jak i klienta? Jeśli tak, warto rozważyć podzielenie ich na osobne aplikacje. Takie podejście ułatwi również wielu osobom pracę nad aplikacjami w tym samym czasie i ograniczy "promień wybuchu" (ilość testów), gdy zmiany w aplikacji wymagają pełnego przejścia testów.

Optymalizacja ForAll

Funkcja ForAll w Power Apps służy do iteracji po tabeli rekordów i zastosowania formuły lub zestawu formuł do każdego rekordu. Chociaż sama funkcja jest wszechstronna, niewłaściwe użycie funkcji ForAll może szybko obniżyć wydajność aplikacji.

Funkcja ForAll jest pojedynczą funkcją sekwencyjną zamiast funkcją współbieżną. Dlatego też analizuje tylko jeden rekord na raz, uzyskuje wynik, a następnie przechodzi do następnego, aż przejrzy wszystkie rekordy w swoim zakresie.

Za wszelką cenę unikaj zagnieżdżania ForAll. Może to prowadzić do wykładniczych iteracji i znacząco wpływać na wydajność.

ClearCollect(FollowUpMeetingAttendees.ForAll(ForAll(Distinct(AttendeesList.EmailAddress.Address).Lookup(Attendees))))

Aktualizacje wsadowe do bazy danych

ForAll + Patch może być jednym z podejść do wsadowej aktualizacji bazy danych. Należy jednak zachować ostrożność podczas korzystania z kolejności For All i Patch.

Następująca funkcja:

Patch(SampleFoodSalesData, ForAll(colSampleFoodSales,
    {
        demoName:"fromCanvas2"
    })
);

Ma lepszą wydajność niż:

ForAll(colSampleFoodSales, Patch(SampleFoodSalesData,
    {
        demoName:"test"
    })
);

Następny krok