Suggerimento rapido come eseguire il debug di un errore AS3 # 1063

È il momento di un altro consiglio rapido per il debug. Continueremo a concentrarci su errori specifici (e comuni) che tendono a ostacolare ActionScripter meno esperti. In questo caso, copriremo l'errore n. 1063, l'errore di mancata corrispondenza del conteggio degli argomenti.


Step 1: Essere cattivi

Innanzitutto, creiamo una situazione in cui si verifica l'errore. Apri un nuovo documento Flash (supponendo che tu stia seguendo insieme a Flash Pro CS3 +, altrimenti questo esempio può essere facilmente adattato a un progetto Flex). Apri lo Script Editor e inserisci il seguente codice:

 import flash.events.MouseEvent; function onClick (): void trace ("click.");  stage.addEventListener (MouseEvent.CLICK, onClick);

Probabilmente è già possibile individuare il problema; se hai trascorso un po 'di tempo a scrivere ActionScript 3 ti sarai trovato a scrivere gestori di eventi. Altrimenti, non sentirti male - ci riprenderemo tutto a tempo debito.

Se si esegue il file Flash così com'è, e quindi si fa clic sullo stage, verrà generato il seguente messaggio di errore in fase di esecuzione:

 ArgumentError: Errore # 1063: mancata corrispondenza del conteggio degli argomenti su Untitled_fla :: MainTimeline / onClick (). Previsto 0, preso 1.

E non arriviamo mai alla dichiarazione di traccia che dovrebbero hanno eseguito dopo aver fatto clic.


Passaggio 2: spezzandolo

Quindi cosa sta succedendo? In questo caso, la verbosità di Adobe per l'errore non è in realtà così grave e, se ti sei abituato a analizzare un messaggio di errore in fase di esecuzione, il suo significato potrebbe essere abbastanza chiaro. Ma non tutti sono intelligenti come te, quindi ecco la ripartizione per tutti gli altri.

ArgumentError -- Questa è un'informazione in qualche modo irrilevante, ma mostra lo specifico Errore classe che è stata lanciata. Abbiamo qualcosa che non è tanto generale quanto semplice Errore, e abbiamo inserito una categorizzazione specifica dell'errore associato agli argomenti (a funzioni e metodi).

Errore # 1063 -- Qui stiamo solo dando il numero di errore formale, come tutti i buoni errori di run-time. È possibile utilizzare questo codice per individuarlo più facilmente nella documentazione di errore in fase di esecuzione di Adobe.

Mancata corrispondenza del conteggio degli argomenti? -- In termini più proletari, c'era un numero errato di argomenti inviati a una funzione. Quale funzione? Suo?

? su Untitled_fla :: MainTimeline / onClick (). -- Ciò identifica semplicemente la funzione che ha ricevuto il numero errato di argomenti.

Previsto 0, preso 1. -- Otteniamo un po 'di informazioni extra in questa descrizione di errore. Questo dettaglio la mancata corrispondenza del conteggio. Questa frase cambierà in base alla natura dell'errore specifico, ma nel nostro caso sta dicendo che la funzione è stata scritta senza alcun argomento nella firma, ma un singolo argomento è stato inviato ad esso comunque.

A Flash piacciono le sue anatre di fila. Quindi, nota questa discrepanza e decide di lanciare a collera errore, perché preferirebbe che tu (lo sviluppatore) capissi cosa è andato storto di quanto hai semplicemente ignorato il problema. Questo è un bene, perché se il conteggio sbagliato è andato nell'altro senso (previsto 1, ottenuto 0), allora saremmo bloccati senza un argomento per un parametro richiesto, e la funzione farebbe Dog sa cosa.


Passaggio 3: la radice del problema

A questo punto, la natura dell'errore dovrebbe essere chiara, ma potreste comunque chiedervi perché si sia verificato. Da dove viene questa argomentazione superflua?

L'argomento non è esattamente superfluo. È previsto, in realtà, dal momento che abbiamo collegato la nostra funzione per essere un ascoltatore di eventi. Il sistema degli eventi in Flash ha la nozione di a oggetto evento che incapsula aspetti dell'evento che si è verificato. Questo oggetto viene passato alla funzione listener come unico argomento. Quindi, noi atteso 0 perché abbiamo scritto la nostra funzione senza parametri, ma noi preso 1 perché il dispatcher dell'evento ha inviato un oggetto evento.

Ora ti starai chiedendo perché il compilatore non abbia rilevato questo errore. È vero: se hai scritto questo:

 function sayClick (): void trace ("click.");  sayClick (42);

Quindi il file SWF non verrà compilato nemmeno, perché otterrai questo errore:

 1137: numero errato di argomenti. Previsto non più di 0.

La differenza è che nel secondo esempio, abbiamo un codice reale che chiama la funzione con il numero sbagliato di argomenti. Cioè, abbiamo scritto la riga in basso che chiama la funzione in modo errato. Il compilatore può guardare la linea che definisce la funzione e la linea che chiama la funzione e confrontarle per le discrepanze e suonare l'allarme quando si verificano.


Immagine di Alan / Falcon

Tuttavia, nell'esempio originale, non è stata scritta una riga di codice che richiama letteralmente la funzione in base al nome. Invece, la funzione è chiamata per riferimento. Quando aggiungiamo il listener di eventi, passiamo nella funzione, ea quel punto si tratta di una variabile, non di una chiamata di funzione. Questo riferimento viene memorizzato dal dispatcher dell'evento e quindi eseguito dinamicamente quando si verifica l'evento (questa è una vera panoramica di alto livello su come funziona il sistema degli eventi, ma non abbiamo il tempo di andare più a fondo). Quindi, la riga di codice che alla fine chiama la funzione che causa l'errore è una linea di codice piuttosto generica che usa l'indirezione per portare a termine il lavoro, e quindi qualcosa di molto più difficile da catturare per il compilatore.

(Secondo me, Adobe potrebbe almeno registrare il addEventListener linea al momento della compilazione, e vai a cercare la funzione di riferimento per nome. Se trova una corrispondenza, potrebbe controllare la firma della funzione per un argomento evento appropriato e produrre errori di conseguenza. Non è stato possibile eseguirlo in modo infallibile, ma potrebbe fare molto per rilevare questi errori prima di eseguire effettivamente il file SWF.

Il punto principale, tuttavia, è che questo errore di runtime ha una controparte in fase di compilazione, ma che l'errore di run-time si verifica quando la funzione viene chiamata per riferimento e non direttamente per nome.


Passaggio 4: fissaggio del foro

Sta arrivando la pioggia quando chiamiamo la funzione per riferimento e abbiamo una discrepanza nel numero di argomenti. Generalmente abbiamo due opzioni: possiamo modificare la chiamata o modificare gli argomenti della funzione. In questo particolare esempio, non possiamo modificare la chiamata, così come accade all'interno EventDispatcher, codice a cui non abbiamo accesso. Questo ci lascia con la modifica degli argomenti.

Questo, di nuovo, ha due opzioni. Innanzitutto, possiamo semplicemente aggiungere l'argomento. Questo allinea il numero di argomenti e da qui in poi, tutto sarà copacetico. Non abbiamo bisogno di usare l'argomento, abbiamo solo bisogno di avere la funzione? quando viene chiamato.

 function onClick (e: MouseEvent): void 

La seconda opzione è, ancora una volta, aggiungere l'argomento (non c'è dubbio, ho paura). Tuttavia, se hai originariamente scritto la funzione come una funzione normale e non come un listener di eventi e la stai chiamando da altrove nel tuo codice senza argomenti, potresti apprezzare questa variazione. Rendi l'argomento facoltativo e impostalo come predefinito nullo:

 function onClick (e: MouseEvent = null): void 

Questo funzionerà bene con il sistema degli eventi: viene inviato un oggetto evento e può catturarlo. Funziona anche bene con il tuo codice esistente; se non viene inviato alcun argomento, viene utilizzato il parametro predefinito e la funzione procede.


Passaggio 5: richiamate

Nota che questo errore non è limitato agli ascoltatori di eventi, anche se questo è probabilmente il contesto più comune in cui lo sperimenterai. In definitiva è l'utilizzo di funzioni memorizzate in variabili, anziché chiamare per nome, che porta all'errore. Questo è il modo in cui funziona il sistema degli eventi. Possiamo rielaborare l'esempio originale per produrre più o meno lo stesso errore, solo senza il clic:

 function sayMyName (name: String): void trace ("Hello," + name);  var funcRef: Function = sayMyName; funcRef ();

Ancora una volta, superiamo l'errore del compilatore perché abbiamo uno strato di riferimento indiretto tra la definizione della funzione e la chiamata alla funzione. Quindi, otteniamo l'errore di run-time (previsto 1, ottenuto 0).

Tuttavia, non è sempre così tagliato e asciutto. Se si utilizzano le callback nel proprio codice, si potrebbe cadere preda dell'errore 1063. I callback sono una specie di listener di eventi simili, solo che non esiste un meccanismo formale incorporato per l'implementazione. Sono fondamentalmente solo funzioni che passano per riferimento, che vengono memorizzate (temporaneamente o a lungo termine) da qualche altro processo, che quindi chiama la funzione di callback al momento opportuno.

I motori di interpolazione tipicamente li implementano. Alcuni optano per un sistema più formale basato sugli eventi, ma TweenLite, ad esempio, utilizza i callback per ricevere notifiche sui progressi dei tween. Questa linea:

 TweenLite.to (someClip, 1, onComplete: tweenFinished, onCompleteParams: [42, "answer"]);

? chiamerebbe una funzione chiamata tweenFinished alla fine dell'interpolazione, passando in due parametri alla funzione. Questa tecnica è in definitiva più flessibile degli eventi, in quanto non si è limitati solo al singolo oggetto evento come parametro. Ma si arrende a vulnerabilità simili all'errore 1063 a causa della natura delle funzioni di passaggio in giro per riferimento.


Questo è tutto

Questo avvolge un altro Suggerimento rapido di debug. Grazie per la lettura, e spero che tu abbia imparato qualcosa lungo la strada!