Come faccio a sapere se la mia funzione asincrona è veramente asincrona?

5

Sto scrivendo una funzione in node.js-style asincrono modo, ma come faccio a sapere se queste funzioni sono veramente asincrone, cioè che funzionano in parallelo e non in modo sequenziale?

Ecco il mio codice (modificato per rimuovere i dettagli):

// write the async function
function compileData(data, callback) {
  try {
    // ... do all the work ...
    callback(null, result); // instead of 'return result;', pass it to the callback
  } catch (err) {
    callback(err, null);
  }
}

// use the async function
compileData(mydata1, function (err, data) {
  if (err) console.error(err);
  else // do something with compiled 'data'
});
compileData(mydata2, function (err, data) {
  if (err) console.error(err);
  else // do something with compiled 'data'
});

Quando utilizzo le funzioni asincrone come sopra, come posso essere sicuro che siano in esecuzione in parallelo? Come faccio a sapere che la seconda chiamata di compileData() non attende l'avvio fino al termine della prima chiamata?

    
posta chharvey 25.04.2017 - 15:53
fonte

4 risposte

3

I termini asincroni e paralleli sono spesso scambiati, sebbene asincroni significhi che qualcosa fuori banda accade in relazione al flusso principale di esecuzione (interrompendo quindi il flusso principale di esecuzione), spesso questa interruzione può essere in servizio di un I / O routine di completamento. Pertanto, async implica un'interruzione (potenzialmente arbitrariamente temporizzata) del thread principale e non necessariamente un secondo thread completo. Su alcuni sistemi (ma non su JavaScript), il thread principale viene temporaneamente sospeso e quindi con jack alto per servire la routine di completamento dell'I / O (quindi il lavoro sospeso viene ripreso).

Mentre parallelamente due o più cose (discussioni) avvengono simultaneamente. Su un uniprocessore non esiste una vera esecuzione parallela; tuttavia, viene simulato interrompendo qualsiasi thread attualmente in esecuzione (e spesso in un punto arbitrario) per dare un po 'di tempo CPU ad un altro thread. Sui sistemi a multiprocessore, ci sarà sia l'esecuzione simultanea di diverse CPU, sia l'interruzione ai fini dell'esecuzione di thread interleaving per eseguire più thread rispetto alla CPU.

(Se lo farai, async è una forma leggera di parallelismo (pseudo), dove l'unica cosa è il thread principale, e l'altra cosa non è necessariamente un vero thread in piena regola, ma piuttosto una routine di completamento dell'I / O .)

Si noti inoltre che JavaScript è intrinsecamente a thread singolo. Vale a dire, non esiste una vera esecuzione parallela anche su un chip multiprocessore, mentre in C, C ++, Java o C #, si può avere davvero l'esecuzione simultanea di thread su un chip multiprocessore. JavaScript non ha nozioni di thread, ma ha callback.

Le callback (riferimenti alle funzioni) che fornite ad altre routine possono essere eseguite in modo sincrono o possono essere eseguite in modo asincrono. Dipende molto da come vengono utilizzati quei callback: in realtà non si può sapere dal codice che passa il callback (senza conoscere la routine della libreria a cui viene fornita la callback). Quindi i callback non implicano immediatamente l'esecuzione asincrona.

(I callback sono ulteriormente complicati in quanto il riferimento alla funzione può effettivamente essere usato zero o più volte, non c'è praticamente alcuna garanzia intrinseca dalla semantica del linguaggio su quando o quante volte viene usata una callback.)

Nel tuo esempio, sembrerebbe che i callback siano eseguiti in modo sincrono rispetto a - e sotto il controllo diretto di - il thread principale.

L'esecuzione asincrona avviene in JavaScript come risultato di routine di completamento I / O (o timeout). Poiché JavaScript è intrinsecamente a thread singolo, il modo in cui funziona è che il thread principale (uno) può essere eseguito al 100% di completamento - per tornare al suo chiamante (che è lo schedulatore JavaScript). A questo punto, non c'è più thread principale in esecuzione e, lo scheduler JavaScript può richiamare routine di completamento usando quel thread principale. Se più richieste di I / O attivano più routine di completamento, ciascuna viene eseguita al 100% al completamento, una dopo l'altra, nell'ordine in cui sono pianificate (che è l'ordine del completamento dell'I / O) senza interleaving.

(Naturalmente, la routine di completamento I / O può effettuare chiamate I / O aggiuntive, passando successivi callback di completamento I / O, l'esecuzione complessiva di tale serie di routine di completamento sarebbe intercalata con altri tali callback di completamento I / O come descritto sopra.)

Nel tuo caso, i callback vengono eseguiti dal richiamo di riferimento alla funzione, che li fa girare sotto il controllo regolare del thread principale. Il meccanismo è una chiamata di funzione indiretta, quindi i callback vengono richiamati utilizzando il meccanismo di chiamata della funzione standard. Il thread principale non viene eseguito fino al completamento; i callback non sono pianificati per essere eseguiti ma vengono richiamati piuttosto direttamente. Per vedere la differenza, potresti sostituire:

callback(null, result);

con

setTimeout(callback,100,null,result);

Ciò richiamerebbe anche il callback, ma attenderebbe qualche istante dopo la routine in esecuzione (e l'intero thread, di fatto) è tornato al suo chiamante.

    
risposta data 25.04.2017 - 17:58
fonte
2

Asincrono significa semplicemente "In nessun ordine particolare", distinto dal codice (ordinariamente) sincrono "In esattamente questo ordine".

L'esecuzione parallela implica Asincrono, poiché non si specifica quale processo | thread | viene eseguito su quale core | worker, e ciò significa che sicuro non deve dipendere dal relativo ordine, né presumere che i valori condivisi rimangono invariati.

Immagina un programmatore per un singolo computer centrale, che mantiene una coda di attività in sospeso. Quel programmatore eseguirà il tuo programma come se fosse sincrono.

    
risposta data 25.04.2017 - 16:18
fonte
2

Stai confondendo le definizioni, asincrono significa che la funzione ritorna subito dopo che è stata chiamata, senza bloccare il flusso di codice ... e puoi ottenere il valore di ritorno più tardi. È come far bollire l'acqua in un bollitore, mettere l'acqua, andare via per fare qualcos'altro e il bollitore ti segnala quando l'acqua è calda ... che è acqua bollente asincrona.

Paralell significa che il codice può essere eseguito simultaneamente su più core della CPU. Quindi metti l'acqua in 2 o più bollitori, accendili subito e questo è paralell.

Ora se hai 2 bollitori E puoi andartene e fare qualcos'altro finché l'acqua non bolle è paralell e asincrono, se hai bisogno di tenere le mani sui bollitori è paralell e sincrono.

Quindi, arrivando a nodejs, il codice non è MAI paralell, perché è single threaded. Hai bisogno di guardare qualche altra lingua, ad es. golang se vuoi il parallelismo.

Nodejs è solo asincrono ... quindi è come se tu potessi avere 2 funzioni che calcolano il numero PI allo stesso tempo, ma funzioneranno solo su core single CPU ... quindi sulla superficie 2 le funzioni sono "in esecuzione" , ma solo uno sta facendo "lavoro" in qualsiasi momento.

C'è un trucco sporco che ti permette di avviare nuovi processi nel nodo, ma è così grave che non dovresti davvero prenderlo in considerazione per nulla. E il design di nodejs è così brutto che è abominio di qualsiasi pratica di programmazione sana. Letteralmente il codice che ha più di 100 linee può essere illeggibile. Anche la gestione degli errori è rotta dalla progettazione, dovresti cercare in golang perché è stato progettato per fare la stessa cosa, è facile da usare, MA tutto funziona e progettato correttamente.

In golang, per scrivere una funzione asincrona basta aggiungere la parola chiave "go" davanti ad essa, questo è tutto ciò che è necessario. Si chiama "a ()" è sincrono, si chiama "vai a ()" è asincrono. E, il meglio ... se chiami "vai a ();" più volte è automaticamente AND asincrono AND paralell.

Non devi ucciderti e perdere tempo a lavorare usando qualcosa che è di design, rotto. So che è un giudizio duro e molte persone hanno investito molto tempo in questo ... ma sono davvero sorpreso che qualcuno usi ancora il nodo ... è stato bello 8 anni fa quando non c'era alternativa. Il tutto è un imbroglio sporco, IMO, che una volta era eccezionale rispetto a PHP ... 8 anni fa, per alcuni casi d'uso molto specifici.

    
risposta data 25.04.2017 - 18:24
fonte
2

Il tuo esempio di codice non è né parallelo né asincrono.

Il codice nell'esempio utilizza una funzione di callback per il controllo del flusso sincrono.

Asynchronous

Se vuoi renderlo asincrono, dovresti fare qualcosa che dia il controllo mentre altri lavori continuano. Esempi tipici sono ...

  • Chiama una funzione database o REST che viene completata immediatamente e richiama una richiamata al termine.
  • Utilizza setTimeout () o setInterval () per posticipare l'esecuzione fino al termine del lavoro corrente.

Nel tuo esempio dovresti aggiungere qualcosa di asincrono, ad esempio

function compileData(data, callback) {
    try {
        // databaseRequest is an asynchronous call that executes immediately.
        // When the request is complete, the library calls the anonymous function, 
        // which calls your callback.
        databaseRequest(data,function(result) {
            callback(null, result);
        });
    } catch (err) {
        callback(err, null);
    }
}

Questo è probabilmente ciò che intendevi, ma per chiarire il punto, in un caso come questo, sai che la chiamata è asincrona semplicemente perché restituisce e continua l'esecuzione immediatamente, e il risultato viene restituito in seguito tramite la funzione anonima.

Se non sei convinto, inserisci alcune istruzioni di console.log () e osserva l'ordine in cui vengono eseguite.

Parallela

Sai che il codice in questione non sta eseguendo funzioni in parallelo perché l'ambiente del nodo è a thread singolo. Se si desidera che vengano eseguiti in parallelo, è necessario avviare un'altra procedura di nodo o utilizzare uno degli strumenti per questo scopo. Questa non è una raccomandazione.

    
risposta data 25.04.2017 - 20:43
fonte

Leggi altre domande sui tag