Sì, le promesse sono callback asincroni. Non possono fare nulla che i callback non possano fare e tu incontri gli stessi problemi con l'asincronia dei callback normali.
Tuttavia, le promesse sono più che semplici callback. Sono un'astrazione molto potente, consentono un codice più pulito e migliore e funzionale con una caldaia meno soggetta a errori.
Qual è l'idea principale?
Le promesse sono oggetti che rappresentano il risultato di un singolo calcolo (asincrono). Essi risolvono a tale risultato solo una volta. Ci sono alcune cose che cosa significa:
Le promesse implementano un modello di osservatore:
- Non è necessario conoscere i callback che utilizzeranno il valore prima che l'attività venga completata.
- Invece di aspettarti callback come argomenti per le tue funzioni, puoi facilmente
return
un oggetto Promise
- La promessa memorizzerà il valore e potrai aggiungere in modo trasparente una richiamata ogni volta che lo desideri. Verrà chiamato quando il risultato è disponibile. "Trasparenza" implica che quando si ha una promessa e si aggiunge un callback, non fa alcuna differenza al codice se il risultato è ancora arrivato - l'API e i contratti sono gli stessi, semplificando molto la memorizzazione nella cache / memorizzazione.
- È possibile aggiungere più callback facilmente
Le promesse sono concatenabili ( monadiche , se vuoi ):
- Se è necessario trasformare il valore rappresentato da una promessa, mappare una funzione di trasformazione sulla promessa e ottenere una nuova promessa che rappresenta il risultato trasformato. Non è possibile ottenere in modo sincrono il valore per usarlo in qualche modo, ma è possibile sollevare facilmente la trasformazione nel contesto della promessa. Nessun callback del plateplate.
- Se si desidera concatenare due attività asincrone, è possibile utilizzare il
.then()
metodo Ci vorrà un callback per essere chiamato con il primo risultato e restituisce una promessa per il risultato della promessa che il callback ritorna.
Sembra complicato? Tempo per un esempio di codice.
var p1 = api1(); // returning a promise
var p3 = p1.then(function(api1Result) {
var p2 = api2(); // returning a promise
return p2; // The result of p2 …
}); // … becomes the result of p3
// So it does not make a difference whether you write
api1().then(function(api1Result) {
return api2().then(console.log)
})
// or the flattened version
api1().then(function(api1Result) {
return api2();
}).then(console.log)
L'appiattimento non arriva magicamente, ma puoi farlo facilmente. Per il tuo esempio fortemente annidato, l'equivalente (quasi) sarebbe
api1().then(api2).then(api3).then(/* do-work-callback */);
Se vedere il codice di questi metodi aiuta a capire, ecco una promessa di base in poche righe .
Qual è il grande clamore delle promesse?
L'astrazione Promise consente una migliore componibilità delle funzioni. Ad esempio, accanto al then
concatenamento, la all
funzione crea una promessa per il risultato combinato di più promesse di attesa parallele.
Ultimo ma non meno importante, le promesse vengono fornite con la gestione integrata degli errori. Il risultato del calcolo potrebbe essere che o la promessa è adempiuta con un valore o è respinta con una ragione. Tutte le funzioni di composizione gestiscono questo automaticamente e propagano gli errori nelle catene di promesse, quindi non è necessario preoccuparsene esplicitamente dappertutto, a differenza di un'implementazione di semplice callback. Alla fine, è possibile aggiungere un callback di errore dedicato per tutte le eccezioni verificatesi.
Per non parlare del fatto di dover convertire le cose in promesse.
È piuttosto banale in realtà con buone librerie di promesse, vedi Come posso convertire un'API di callback esistente in promesse?