Qual è la differenza tra le promesse JavaScript e l'attesa asincrona?


95

Ho già utilizzato le funzionalità ECMAScript 6 ed ECMAScript 7 (grazie a Babel) nelle mie applicazioni, sia mobili che web.

Il primo passo ovviamente è stato quello di ECMAScript 6 livelli. Ho imparato molti schemi asincroni, le promesse (che sono davvero promettenti), i generatori (non so perché il simbolo *), ecc. Da questi, le promesse si adattavano abbastanza bene al mio scopo. E li ho usati parecchio nelle mie applicazioni.

Ecco un esempio / pseudocodice di come ho implementato una promessa di base-

var myPromise = new Promise(
    function (resolve,reject) {
      var x = MyDataStore(myObj);
      resolve(x);
    });

myPromise.then(
  function (x) {
    init(x);
});

Col passare del tempo, mi sono imbattuto nelle funzionalità di ECMAScript 7 e una di queste è ASYNCe AWAITparole chiave / funzioni. Questi insieme fanno grandi meraviglie. Ho iniziato a sostituire alcune delle mie promesse con async & await. Sembrano aggiungere un grande valore allo stile di programmazione.

Di nuovo, ecco uno pseudocodice di come appare la mia funzione async, wait-

async function myAsyncFunction (myObj) {
    var x = new MyDataStore(myObj);
    return await x.init();
}
var returnVal = await myAsyncFunction(obj);

Tenendo da parte gli errori di sintassi (se presenti), entrambi fanno esattamente la stessa cosa, è quello che sento. Sono quasi riuscito a sostituire la maggior parte delle mie promesse con async, attende.

Perché è necessario async, wait quando le promesse fanno un lavoro simile?

Async, attende risolve un problema più grande? O era solo una soluzione diversa per richiamare l'inferno?

Come ho detto prima, sono in grado di usare promesse e asincrono, aspetto di risolvere lo stesso problema. C'è qualcosa di specifico che l'asincronia attende risolto?

Note aggiuntive:

Ho utilizzato ampiamente async, attende e promette nei miei progetti React e nei moduli Node.js. React in particolare è stato un early bird e ha adottato molte funzionalità ECMAScript 6 ed ECMAScript 7.


3
Il tuo primo blocco di codice sembra utilizzare una promessa per un'operazione sincrona. Perché dovresti farlo? Sincrono è, per sua natura, più facile scrivere codice, quindi ci dovrebbero essere pochi motivi per racchiudere un'operazione sincrona in una promessa e costringerla a essere asincrona.
jfriend00

@ jfriend00 Sì, hai ragione. Ha modificato il codice. Grazie.
bozzmob

2
Stai ancora cercando di utilizzare strumenti asincroni con funzioni sincrone, ora in entrambi i blocchi di codice. Perché?
jfriend00

@ jfriend00 Ok. Qui ho il mio codice gist.github.com/bozzmob/26d38b83dc37d1be37f5 . Per favore, puoi dirmi cosa sto facendo di sbagliato?
bozzmob

10
Sembra che tu abbia solo bisogno di leggere un po 'per capire a cosa servono async e await. Ecco alcuni articoli: La lunga strada per Async / Await in JavaScript e Simplifying Asynchronous Coding with ES7 Async Functions and Taming the asynchronous beast with ES7 .
jfriend00

Risposte:


74

Perché è necessario async, wait quando Promises fa un lavoro simile? Async, attende risolve un problema più grande?

async/awaitti dà semplicemente una sensazione sincrona al codice asincrono. È una forma molto elegante di zucchero sintattico.

Per query semplici e manipolazione dei dati, Promises può essere semplice, ma se ti imbatti in scenari in cui è presente una manipolazione complessa dei dati e quant'altro, è più facile capire cosa sta succedendo se il codice sembra semplicemente sincrono (per dirla in un altro modo, la sintassi in sé e per sé è una forma di "complessità incidentale" che async/awaitpuò aggirare).

Se sei interessato a sapere, puoi usare una libreria come co(insieme ai generatori) per dare lo stesso tipo di sensazione. Cose come questa sono state sviluppate per risolvere il problema che alla async/awaitfine risolve (nativamente).


Per favore, puoi approfondire cosa significa "complessità incidentale"? Inoltre, quando si tratta di prestazioni, non c'è differenza tra i due?
bozzmob

@bozzmob, shaffner.us/cs/papers/tarpit.pdf <- spiega la "complessità incidentale" lì dentro. Per quanto riguarda la tua domanda sulle prestazioni, ne dubito, specialmente con il motore V8 che è quello che è. Sono sicuro che ci sono alcuni test di prestazione là fuori, ma non me ne preoccuperei troppo. Non perdere tempo con la microottimizzazione quando non è necessaria.
Josh Beam

1
Molte grazie! Questa è un'ottima informazione che ho ricevuto da te. E sì, non esaminerà le micro ottimizzazioni.
bozzmob

Ho trovato utile questa spiegazione nikgrozev.com/2015/07/14/…
mwojtera

33

Async / Await fornisce una sintassi molto migliore in scenari più complessi. In particolare, tutto ciò che ha a che fare con i loop o con certi altri costrutti come try/ catch.

Per esempio:

while (!value) {
  const intermediate = await operation1();
  value = await operation2(intermediate);
}

Questo esempio sarebbe notevolmente più complicato usando solo Promises.


Questo è un ottimo esempio per capire lo stesso. Quindi, quando si tratta di prestazioni, non c'è differenza tra i due? E quale è meglio usare nel codice? Async Await sembra migliore dopo aver visto almeno il tuo esempio.
bozzmob

1
@bozzmob: non c'è differenza nelle prestazioni. Se ti senti a tuo agio nell'usare async / await, lo consiglierei. Non lo uso ancora perché non fa parte dello standard ufficiale.
Stephen Cleary

Sì, sono d'accordo che non fa parte dello standard, ma, nel caso di ReactJS (reagire in modo specifico), sono un po 'costretto a usarlo in alcune parti del codice. Quindi, metà di esse sono promesse e metà sono attese asincrone. Quindi, ti ho fatto quelle domande. Grazie per le informazioni necessarie.
bozzmob

1
Penso che molte persone siano confuse e / o fuorviate quando nessuno usa il blocco try / catch nei loro esempi di codice.
Augie Gardner,

Intendi così? const getValue = value => value || operation1().then(operation2).then(getValue);
Sharcoux

13

Perché è necessario async, wait quando Promises fa un lavoro simile? Async, attende risolve un problema più grande? o era solo una soluzione diversa per richiamare l'inferno? Come ho detto prima, sono in grado di utilizzare Promises e Async, Await per risolvere lo stesso problema. C'è qualcosa di specifico che Async Await ha risolto?

Le prime cose che devi capire che async/ awaitsyntax è solo zucchero sintattico che ha lo scopo di aumentare le promesse. In effetti il ​​valore di ritorno di una asyncfunzione è una promessa. async/ awaitsyntax ci dà la possibilità di scrivere in modo asincrono in modo sincrono. Ecco un esempio:

Promessa di concatenamento:

function logFetch(url) {
  return fetch(url)
    .then(response => response.text())
    .then(text => {
      console.log(text);
    }).catch(err => {
      console.error('fetch failed', err);
    });
}

Async funzione:

async function logFetch(url) {
  try {
    const response = await fetch(url);
    console.log(await response.text());
  }
  catch (err) {
    console.log('fetch failed', err);
  }
}

Nell'esempio precedente, awaitattende che la promessa ( fetch(url)) venga risolta o rifiutata. Se la promessa viene risolta, il valore viene memorizzato nella responsevariabile e se la promessa viene rifiutata genera un errore e quindi entra nel catchblocco.

Possiamo già vedere che l'uso di async/ awaitpotrebbe essere più leggibile del concatenamento di promesse. Ciò è particolarmente vero quando la quantità di promesse che stiamo utilizzando aumenta. Sia Promise chaining che async/ awaitrisolvono il problema dell'inferno di callback e il metodo scelto dipende dalle preferenze personali.


7

Confronto completo con pro e contro.

JavaScript normale

  • Professionisti
  • Non richiede alcuna libreria o tecnologia aggiuntiva
  • O ff re le migliori prestazioni
  • Fornisce il miglior livello di compatibilità con le librerie di terze parti
  • Consente la creazione di algoritmi ad hoc e più avanzati
  • Contro
  • Potrebbe richiedere codice extra e algoritmi relativamente complessi

Async (libreria)

  • Professionisti
  • Semplifica i modelli di flusso di controllo più comuni
  • È ancora una soluzione basata su callback
  • Buona performance
  • Contro
  • Introduce una dipendenza esterna
  • Potrebbe ancora non essere sufficiente per i flussi avanzati

Promesse

  • Professionisti
  • Semplifica notevolmente i modelli di flusso di controllo più comuni
  • Robusta gestione degli errori
  • Parte della speci fi ca ES2015
  • Garantisce l'invocazione differita di onFulfilled e onRejected
  • Contro
  • Richiede API basate su callback promesse
  • Introduce un piccolo successo in termini di prestazioni

Generatori

  • Professionisti
  • Rende l'API non bloccante come un'API di blocco
  • Semplifica la gestione degli errori
  • Parte delle speci fi che ES2015
  • Contro
  • Richiede una libreria di flusso di controllo complementare
  • Richiede ancora callback o promesse di implementare flussi non sequenziali
  • Richiede thunkify o promettere API non basate su generatore

Async attende

  • Professionisti
  • Fa sembrare l'API non bloccante un blocco
  • Sintassi pulita e intuitiva
  • Contro
  • Richiede Babel o altri transpilers e alcune configurazioni da utilizzare oggi

Da dove è stato copiato? Almeno una parte si trova a pagina 136-137 nel libro Node.js Design Patterns (seconda edizione) (ISBN-10: 1785885588)
Peter Mortensen

6

Async / await può aiutare a rendere il codice più pulito e più leggibile nei casi in cui è necessario un flusso di controllo complicato. Produce anche codice più adatto al debug. E consente di gestire errori sia sincroni che asincroni con appena try/catch.

Recentemente ho scritto questo post che mostra i vantaggi di async / await rispetto alle promesse in alcuni casi d'uso comuni con esempi di codice: 6 motivi per cui JavaScript Async / Await Blows Promises Away (Tutorial)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.