Gestione degli errori
Nota
Il comportamento descritto in questo articolo è disponibile solo quando la funzionalità di anteprima Gestione errori a livello di formula in Impostazioni>Funzionalità in arrivo>Anteprima è attivata. Altre informazioni: Controllo delle funzionalità abilitate
Gli errori accadono. Le reti subiscono interruzioni, lo spazio di archiviazione si esaurisce e si introducono valori imprevisti. È importante che la logica continui a funzionare correttamente davanti a potenziali problemi.
Per impostazione predefinita, gli errori passano attraverso le formule di un'app e vengono segnalati all'utente finale dell'app. In questo modo, l'utente finale sa che si è verificato un imprevisto, può potenzialmente risolvere il problema da solo con un input diverso oppure può segnalare il problema al proprietario dell'app.
In qualità di autore di app, puoi assumere il controllo degli errori nell'app:
- Rilevando e gestendo un errore. Se esiste la possibilità che si verifichi un errore, è possibile scrivere le formule dell'app per rilevare la condizione di errore e riprovare l'operazione. L'utente finale non deve preoccuparsi che si sia verificato un errore perché l'autore ha messo in conto la possibilità. Questa operazione viene eseguita con le funzioni IfError, IsError e IsErrorOrBlank all'interno di una formula.
- Segnalando un errore. Se un errore non viene gestito nella formula in cui è stato rilevato, l'errore viene riportato al gestore App.OnError. In questo caso l'errore non può più essere sostituito poiché si è già verificato e fa parte dei calcoli della formula. Tuttavia, puoi usare App.OnError per controllare il modo in cui l'errore viene segnalato all'utente finale, inclusa la soppressione totale della segnalazione dell'errore. App.OnError fornisce anche un choke comune puntare per la segnalazione degli errori nell'intera app.
- Creando e rigenerando un errore. Infine, puoi rilevare una condizione di errore con la tua logica, una condizione specifica dell'app. Usa la funzione Error per creare errori personalizzati. La funzione Error viene anche usata per rigenerare un errore dopo l'interrogazione in IfError o App.OnError.
Introduzione
Iniziamo con un semplice esempio.
- Crea una nuova schermata in un'app canvas Power Apps.
- Inserisci un controllo TextInput. Il nome predefinito sarà TextInput1.
- Inserisci un controllo Label.
- Imposta la proprietà Text del controllo Label sulla formula
1/Value( TextInput1.Text )
Si è verificato un errore perché il testo predefinito di un controllo TextInput è "Text input"
, convertibile in un numero. Per impostazione predefinita, questa è una buona cosa: l'utente finale riceverà una notifica che qualcosa non funziona come previsto nell'app.
Ovviamente, non vogliamo che l'utente riceva un errore ogni volta che avvia questa app. Probabilmente, "Text input"
non è il controllo predefinito giusto per la casella di testo. Per risolvere l'errore, cambiamo la proprietà Default del controllo TextInput su:
Blank()
Ora abbiamo un errore diverso. Le operazioni matematiche con blank, ad esempio la divisione, vincoleranno il valore blank a zero. E questo ora sta causando un errore di divisione per zero. Per risolvere l'errore, dobbiamo individuare il comportamento appropriato per questa situazione in questa app. La risposta potrebbe consistere nel mostrare blank quando l'input di testo è blank. Possiamo eseguire questa operazione eseguendo il wrapping della formula con la funzione IfError:
IfError( 1/Value( TextInput1.Text ), Blank() )
Ora l'errore viene sostituito da un valore valido e il banner scompare. Forse non l'abbiamo precisato, ma IfError che abbiamo usato copre tutti gli errori, inclusa la digitazione di un valore non valido come "hello"
. Possiamo gestire questo problema regolando IfError per gestire solo il caso della divisione per zero e rigenerando tutti gli altri errori:
IfError( 1/Value( TextInput1.Text ),
If( FirstError.Kind = ErrorKind.Div0, Blank(), Error( FirstError ) ) )
Eseguiamo l'app e proviamo valori diversi.
Senza valori, ad esempio all'avvio dell'app, non viene visualizzata alcuna risposta poiché il valore predefinito è blank, ma non vengono visualizzati errori poiché IfError sostituisce l'errore di divisione per zero.
Se digitiamo un 4, otteniamo il risultato previsto di 0,25:
E se digitiamo qualcosa di non valido, ad esempio hello
, riceveremo un banner di errore:
Questo è un semplice esempio introduttivo. La gestione degli errori può essere eseguita in modi diversi, a seconda delle esigenze dell'app:
- Anziché un banner di errore, avremmo potuto mostrare "#Error" nel controllo label con la formula. Per mantenere i tipi delle sostituzioni compatibili con il primo argomento su IfError, dobbiamo convertire in modo esplicito il risultato numerico in una stringa di testo con la funzione Text.
IfError( Text( 1/Value( TextInput1.Text ) ), If( FirstError.Kind = ErrorKind.Div0, Blank(), "#Error" )
- Anziché eseguire il wrapping di questa istanza specifica con IfError, avremmo potuto scrivere un gestore App.OnError centralizzato. Non possiamo sostituire la stringa mostrata con "#Error" poiché l'errore si è già verificato e App.OnError viene fornito solo per controllare la segnalazione.
If( FirstError.Kind <> ErrorKind.Div0, Error( FirstError ) )
Propagazione degli errori
Gli errori passano attraverso le formule proprio come avviene in Excel. In Excel, ad esempio, se la cella A1
contiene la formula =1/0
, A1 visualizzerà il valore dell'errore #DIV0!
:
Se la cella A2
si riferisce a A1
con una formula come =A1*2
, l'errore si propaga anche attraverso quella formula:
L'errore sostituisce il valore che sarebbe stato altrimenti calcolato. Non vi è alcun risultato per la moltiplicazione nella cella A2
, solo l'errore della divisione in A1
.
Power Fx funziona allo stesso modo. In generale, se viene fornito un errore come argomento di una funzione o di un operatore, l'operazione non avrà luogo e l'errore di input passerà come il risultato dell'operazione. Ad esempio, Mid( Text( 1/0 ), 1, 1 )
restituirà un errore di divisione per zero, poiché l'errore più interno passa attraverso la funzione Text e la funzione Mid:
In generale, gli errori non passano attraverso le proprietà di controllo di Power Apps. Estendiamo l'esempio precedente con un controllo aggiuntivo che mostra se la proprietà Text
della prima etichetta è uno stato di errore:
È opportuno che gli errori non si propaghino attraverso un controllo perché il sistema osserverà gli errori sull'input a tutte le proprietà del controllo. L'errore non andrà perso.
La maggior parte delle funzioni e degli operatori segue la regola "errore in entrata, errore in uscita", ma ci sono alcune eccezioni. Le funzioni IsError, IsErrorOrBlank e IfError sono progettate per gestire gli errori in modo che non ne venga restituito uno anche se uno passa.
Osservazione degli errori
Gli errori non vengono osservati finché non viene usato il relativo valore.
Di conseguenza, le funzioni If e Select potrebbero anche non restituire un errore se ne passa uno. Considera la formula If( false, 1/0, 3 )
. In questa formula è presente un errore di divisione per zero, ma poiché If
non assume quel ramo a causa di false
, Power Fx e Power Apps non segnaleranno un errore:
Se si usa la funzione Set con un errore, l'errore non verrà segnalato al punto in cui era stato inserito nella variabile. Ad esempio in Power Apps, ecco una formula in App.OnStart che inserisce un errore di divisione per zero nella variabile x
:
Non viene segnalato alcun errore perché non si fa riferimento a x
. Tuttavia, nel momento in cui aggiungiamo un controllo label e ne impostiamo la proprietà Text su x
, viene visualizzato l'errore:
Puoi osservare errori all'interno di una formula con le funzioni IfError, IsError e IsErrorOrBlank. Con queste funzioni puoi restituire un valore alternativo, eseguire un'azione alternativa o modificare l'errore prima che venga osservato e segnalato.
Segnalazione degli errori
Dopo aver osservato un errore, il passaggio successivo consiste nel segnalarlo all'utente finale.
A differenza di Excel, non è sempre disponibile una posizione pratica per mostrare un risultato di errore, poiché il risultato di una formula potrebbe generare una proprietà come le coordinate X e Y di un controllo per il quale non esiste una posizione pratica per mostrare del testo. Ogni host Power Fx controlla il modo in cui gli errori vengono mostrati all'utente finale e quanto controllo ha l'autore su questo processo. In Power Apps viene mostrato un banner di errore e App.OnError viene usato per controllare il modo in cui viene segnalato l'errore.
È importante notare che App.OnError non può sostituire l'errore nello stesso modo di IfError. Nel punto in cui App.OnError viene eseguito, l'errore si è già verificato e il risultato si è propagato ad altre formule. App.OnError controlla solo il modo in cui l'errore viene segnalato all'utente finale e fornisce un collegamento al produttore per registrare l'errore, se lo desidera.
Le variabili di ambito FirstError e AllErrors forniscono informazioni di contesto sull'errore o gli errori. Fornisce informazioni sul tipo di errore, sulla relativa origine e sul punto in cui è stato osservato.
Interruzione dopo un errore
Le formule di comportamento supportano l'azione, la modifica di database e il cambiamento di stato. Queste formule consentono di eseguire più di un'azione in sequenza usando l'operatore di concatenamento ;
(o ;;
a seconda delle impostazioni locali).
In questo caso, ad esempio, il controllo grid mostra il contenuto della tabella T
. Ogni selezione di pulsante cambia lo stato in questa tabella con due chiamate Patch:
In una formula di comportamento concatenato, le azioni non si interrompono dopo il primo errore. Modifichiamo l'esempio per passare un numero di indice non valido nella prima chiamata Patch. La seconda chiamata Patch continua nonostante l'errore precedente. Il primo errore viene segnalato all'utente finale e mostrato come tale in Studio sul controllo:
IfError può essere utilizzato per interrompere l'esecuzione dopo un errore. Analogamente alla funzione If, il terzo argomento di questa funzione fornisce un punto in cui inserire le azioni da eseguire solo se non si verificano errori:
Se si verifica un errore durante una delle iterazioni di ForAll, le iterazioni rimanenti non si interrompono. ForAll è progettato per eseguire ogni iterazione in modo indipendente, consentendo l'esecuzione parallela. Al completamento di ForAll, viene restituito un errore, che contiene tutti gli errori rilevati (esaminando AllErrors in IfError o App.OnError).
Ad esempio, la seguente formula restituirà ForAll con due errori (per la divisione per zero per Value
di 0, due volte) e Collection
conterrà tre record (per quando Value
non è 0): [1, 2, 3]
.
Clear( Collection );
ForAll( [1,0,2,0,3], If( 1/Value > 0, Collect( Collection, Value ) ) );
Gestione di più errori
Poiché una formula di comportamento può eseguire più di un'azione, può anche rilevare più di un errore.
Per impostazione predefinita, il primo errore viene segnalato all'utente finale. In questo esempio, entrambe le chiamate Patch avranno esito negativo, la seconda con un errore di divisione per zero. All'utente viene mostrato solo il primo errore (sull'indice):
La funzione IfError e App.OnError possono accedere a tutti gli errori rilevati con la variabile di ambito AllErrors. In questo caso, possiamo impostarlo su una variabile globale e osservare gli errori rilevati. Appaiono nella tabella nello stesso ordine in cui sono stati rilevati:
È possibile che più errori vengano restituiti anche nelle formule non di comportamento. Ad esempio, l'uso della funzione Patch con un batch di record da aggiornare può restituire più errori, uno per ogni record non riuscito.
Errori nelle tabelle
Come osservato in precedenza, le variabili possono archiviare errori. Gli errori possono anche essere inclusi in strutture dati, ad esempio tabelle. Questo è importante in modo che un errore in qualsiasi record non renda nulla l'intera tabella.
Ad esempio, considera questo controllo data table in Power Apps:
Il calcolo in AddColumns ha rilevato un errore di divisione per zero per uno dei valori. Per quel record, la colonna Reciprocal ha un valore di errore (divisione per zero), ma gli altri record no, pertanto sono corretti. IsError( Index( output, 2 ) )
restituisce falso e IsError( Index( output, 2 ).Value )
restituisce vero.
Se si verifica un errore durante il filtro di una tabella, l'intero record è un errore ma viene comunque restituito nel risultato in modo che l'utente finale sappia che c'è un problema.
Usiamo questo esempio. Qui, la tabella originale non ha errori, ma l'azione di filtro crea un errore ogni volta che Value è uguale a 0:
I valori -5 e -3 sono filtrati correttamente. I valori 0 restituiscono un errore nell'elaborazione del filtro, pertanto non è chiaro se il record debba essere incluso o meno nel risultato. Per ottimizzare la trasparenza per gli utenti finali e aiutare gli autori a eseguire il debug, includiamo un record di errore al posto dell'originale. In questo caso, IsError( Index( output, 2 ) )
restituisce true.
Errori dell'origine dati
Le funzioni che modificano i dati nelle origini dati, ad esempio Patch, Collect, Remove, RemoveIf, Update, UpdateIf e SubmitForm segnalano gli errori in due modi:
- Ognuna di queste funzioni restituirà un valore di errore come risultato dell'operazione. Gli errori possono essere rilevati con IsError e sostituiti o eliminati con IfError e App.OnError come abitualmente.
- Dopo l'operazione, la funzione Errors restituirà anche gli errori delle operazioni precedenti. Ciò può essere utile per visualizzare il messaggio di errore su una schermata modulo senza la necessità di acquisire l'errore in una variabile di stato.
Ad esempio, questa formula verificherà la presenza di un errore da Collect e visualizzerà un messaggio di errore personalizzato:
IfError( Collect( Names, { Name: "duplicate" } ),
Notify( $"OOPS: { FirstError.Message }", NotificationType.Warning ) )
La funzione Errors restituisce anche informazioni sugli errori passati durante le operazioni di runtime. Può essere utile per visualizzare un errore su una schermata modulo senza la necessità di acquisire l'errore in una variabile di stato.
Rigenerazione di errori
Talvolta, sono previsti alcuni potenziali errori che possono essere ignorati. All'interno di IfError e App.OnError, se viene rilevato un errore che deve essere passato al gestore superiore successivo, può essere rigenerato con Error( AllErrors )
.
Creazione di propri errori
Puoi anche creare i tuoi errori con la funzione Error.
Se crei i tuoi errori, ti consigliamo di usare valori superiori a 1.000 per evitare potenziali conflitti con futuri valori di errore di sistema.
Valori di enumerazione ErrorKind
Enumerazione ErrorKind | Valore | Descrizione |
---|---|---|
AnalysisError | 18 | Errore di sistema. Si è verificato un problema con l'analisi del compilatore. |
BadLanguageCode | 14 | È stato usato un codice lingua non valido o non riconosciuto. |
BadRegex | 15 | Espressione regolare non valida. Verifica la sintassi usata con le funzioni IsMatch, Match o MatchAll. |
Conflitto | 6 | Il record in corso di aggiornamento è già stato modificato all'origine e il conflitto deve essere risolto. Una soluzione comune consiste nel salvare eventuali modifiche locali, aggiornare il record e riapplicare le modifiche. |
ConstraintViolated | 8 | Il record non ha superato un controllo di vincolo sul server. |
CreatePermission | 3 | L'utente non dispone dell'autorizzazione per la creazione di record per l'origine dati. Ad esempio, è stata chiamata la funzione Collect. |
DeletePermissions | 5 | L'utente non dispone dell'autorizzazione per l'eliminazione di record per l'origine dati. Ad esempio, è stata chiamata la funzione Remove. |
Div0 | 13 | Divisione per zero. |
EditPermissions | 4 | L'utente non dispone dell'autorizzazione per la creazione di record per l'origine dati. Ad esempio, è stata chiamata la funzione Patch. |
GeneratedValue | 9 | È stato erroneamente passato al server un valore per un campo calcolato automaticamente dal server. |
InvalidFunctionUsage | 16 | Utilizzo non valido di una funzione. Spesso uno o più argomenti della funzione non sono corretti o sono usati in modo non valido. |
FileNotFound | 17 | Impossibile trovare l'archiviazione SaveData. |
InsufficientMemory | 21 | La memoria o lo spazio di archiviazione sul dispositivo non è sufficiente per l'operazione. |
InvalidArgument | 25 | Argomento non valido passato a una funzione. |
Internal | 26 | Errore di sistema. Si è verificato un problema interno con una delle funzioni. |
MissingRequired | 2 | Campo obbligatorio di un record mancante. |
Network | 23 | Si è verificato un problema con le comunicazioni di rete. |
None | 0 | Errore di sistema. Nessun errore. |
NotApplicable | 27 | Nessun valore disponibile. Utile per differenziare un valore blank che può essere trattato come uno zero nei calcoli numerici da valori vuoti che devono essere contrassegnati come un potenziale problema se il valore viene usato. |
NotFound | 7 | Impossibile trovare il record. Ad esempio, il record da modificare nella funzione Patch. |
NotSupported | 20 | Operazione non supportata da questo dispositivo o lettore. |
Numeric | 24 | Una funzione numerica è stata usata in modo improprio. Ad esempio, Sqrt con -1. |
QuotaExceeded | 22 | Quota archiviazione superata. |
ReadOnlyValue | 10 | La colonna è di sola lettura e non può essere modificata. |
ReadPermission | 19 | L'utente non dispone dell'autorizzazione per la lettura di record per l'origine dati. |
Sync | 1 | È stato identificato un errore dall'origine dati. Controlla la colonna dei messaggi per altre informazioni. |
Unknown | 12 | Si è verificato un errore di tipo sconosciuto. |
Validation | 11 | Il record non ha superato un controllo di convalida. |