La capacità di avere ha funzioni annidate è una buona cosa, ma ovviamente qualsiasi codice che sia confuso non è una buona cosa. Questo tipo di codice è onnipresente nel contesto di una programmazione asincrona di cui il tuo codice sembra essere un esempio.
Le promesse possono renderlo un po 'meno fugace, ma non risolvono completamente il problema.
Ci sono due soluzioni a questo. Utilizza i thread o utilizza le continuazioni.
È facile adattare un'API asincrona a una bloccante utilizzando thread e praticamente qualsiasi tipo di costrutto di sincronizzazione. Questo è ciò che fa AwaitKit . Fondamentalmente, si attiva solo un evento asincrono e nel richiamo di completamento si segnala un semaforo, mentre si attende il semaforo nel thread originale. E.g. in AwaitKit .
Anche le continuazioni di prima classe possono essere utilizzate per risolvere questo problema. Si cattura la continuazione di corrente e la si passa come richiamo all'operazione asincrona, quindi si abbandona il flusso di controllo corrente, ad es. tornando. Con solo un po 'di wrapping, puoi rendere un'API asincrona simile a un'API di blocco con questo approccio. Poche lingue supportano continuazioni di prima classe, però. Per modellarli, puoi usare lo stile di passaggio di continuazione (o lo stile monadico per un controllo un po 'maggiore), e in effetti, questo è esattamente ciò che stanno facendo questi "callback annidati".
La sintassi async
/ await
resa popolare da C # è stata creata per risolvere questo problema. Concettualmente (ma non in realtà) esegue una trasformazione di stile di passaggio di continuazione locale, e da lì è facile rendere un'API asincrona simile a una di blocco. (La trasformazione effettiva è molto più grossa ma efficiente nel contesto di C # che non gestisce le funzioni annidate in modo efficiente.) Questa è una soluzione abbastanza buona, ma Swift attualmente non supporta tale sintassi.
Questo post del blog che non ho letto completamente sembra dettagliare alcune delle opzioni correnti nel Ecosistema rapido oltre a spiegare alcuni dei limiti. C # non ha aggiunto async
/ await
alla lingua e al compilatore senza motivo.