La natura a thread singolo di JavaScript/Typescript: programmazione asincrona

Jan 20 2023
Nel mio primo articolo ho scritto su alcune delle differenze tra JS e TS. Ora esploreremo la natura asincrona come un singolo linguaggio a thread.

Nel mio primo articolo ho scritto su alcune delle differenze tra JS e TS.

Ora esploreremo la natura asincrona come un singolo linguaggio a thread.

In JavaScript e TypeScript, la natura a thread singolo significa che è possibile eseguire solo un'attività alla volta.

D'altra parte, la programmazione asincrona si riferisce alla capacità del linguaggio di eseguire attività in modo asincrono, consentendo al thread principale di esecuzione di continuare a funzionare in attesa del completamento di altre attività. Questo si ottiene attraverso l'uso di callback , eventi , promesse e async / attendi .

Prima di iniziare a spiegarli in termini di codifica, vorrei parlare di un riferimento molto interessante su come le attività asincrone di un linguaggio a thread singolo siano molto simili al nostro cervello quando proviamo a eseguire il multitasking .

In questa sezione riassumerò un lungo testo/capitolo scritto da Kyle Simpson nel suo libro "You Don't Know Javascript" sulla connessione di Sequential Brain con l'asincronizzazione. Se sei interessato solo alla parte di codifica di come funziona, puoi saltare questa parte.

“ Sono abbastanza sicuro che la maggior parte di voi abbia sentito qualcuno dire (anche se l'ha fatto voi stessi): “ Sono un multitasking. Ma
siamo multitasking? Possiamo davvero fare due azioni coscienti e intenzionali contemporaneamente e pensare/ragionare su entrambe esattamente nello stesso momento? Il nostro più alto livello di funzionalità cerebrale ha il multithreading parallelo in corso?

La risposta potrebbe sorprenderti ed è: probabilmente no.

Non è proprio così che i nostri cervelli sembrano essere impostati. Siamo molto più single tasker di quanto molti di noi vorrebbero ammettere. Possiamo davvero pensare solo a una cosa in un dato istante.

Non sto parlando di tutte le nostre funzioni cerebrali involontarie, subconsce e automatiche, come il battito cardiaco, la respirazione e il battito delle palpebre. Questi sono tutti compiti vitali per la nostra vita sostenuta, ma non assegniamo loro intenzionalmente alcun potere cerebrale.

Secondo Simpson, gli esseri umani non sono in grado di eseguire veramente il multitasking nello stesso modo in cui può farlo un computer. Sebbene sia vero che il cervello umano può elaborare più compiti contemporaneamente, non è in grado di prestare la stessa attenzione a tutti i compiti contemporaneamente. Invece, spostiamo rapidamente la nostra attenzione tra le attività, proprio come un programma a thread singolo può eseguire solo un'attività alla volta.

Per fortuna, mentre siamo ossessionati dal controllare i feed dei social network per la quindicesima volta in tre minuti, il nostro cervello continua in background (thread!) con tutti quei compiti importanti.

Quando falsifichiamo il multitasking, ad esempio cercando di digitare qualcosa nello stesso momento in cui stiamo parlando al telefono con un amico o un familiare, ciò che molto probabilmente stiamo facendo è agire come veloci commutatori di contesto . In altre parole, passiamo avanti e indietro tra due o più attività in rapida successione, progredendo simultaneamente su ogni attività in piccoli e veloci blocchi. Lo facciamo così velocemente che al mondo esterno sembra che stiamo facendo queste cose in parallelo.

Ti sembra una concorrenza con eventi asincroni (proprio come quello che succede in JS) per te ?!

C'è una grande differenza osservabile tra il modo in cui pianifichiamo i vari compiti e il modo in cui i nostri cervelli li gestiscono effettivamente.
Anche se a livello operativo i nostri cervelli sono eventi asincroni, sembra che pianifichiamo le attività in modo sequenziale e sincrono. "Devo andare al negozio, poi comprare del latte, poi consegnare il mio lavaggio a secco."

Riesci davvero a immaginare di avere una linea di pensiero che pianifichi le tue commissioni da fare in questo modo:

" Devo andare al negozio (1), ma lungo la strada sono sicuro che riceverò una telefonata (2) , quindi 'Ciao, mamma', e mentre lei inizia a parlare, guarderò in alto l'indirizzo del negozio (3) sul GPS, ma ci vorrà un secondo per caricarsi, quindi abbasso la radio (4) per sentire meglio la mamma...
poi mi rendo conto di aver dimenticato di mettermi una giacca ( 5) e fuori fa freddo, ma non importa, continua a guidare e a parlare con la mamma...
e poi il tintinnio della cintura di sicurezza mi ricorda di allacciarmi (6) , quindi 'Sì, mamma, indosso la cintura di sicurezza, la indosso sempre!'. Ah, finalmente:

il GPS ha le indicazioni, adesso...”

Per quanto ridicola possa sembrare una formulazione per come pianifichiamo la nostra giornata e pensiamo a cosa fare e in quale ordine, tuttavia è esattamente come il nostro cervello opera a livello funzionale. Ma ricorda, non è multitasking, è solo un rapido cambio di contesto.

Con questo in mente, diamo un'occhiata più da vicino a come funziona la programmazione asincrona in JavaScript.

Ora alla codifica :

Esistono diversi modi per eseguire la programmazione asincrona in JavaScript/Typescript, come accennato all'inizio di questo articolo, incluso l'utilizzo di: Callback , Events, Promises, Async/Await.

  • Un callback è una funzione che viene passata come argomento a un'altra funzione e viene eseguita dopo che la funzione esterna è stata completata. Per esempio:
  • function greet(name, callback) {
      console.log(`Hello, ${name}!`);
      callback();
    }
    
    function sayGoodbye() {
      console.log("Goodbye!");
    }
    
    greet("John", sayGoodbye);
    // Output: "Hello, John!"
    // Output: "Goodbye!"
    

  • Un evento è un segnale che qualcosa è accaduto e un ascoltatore è una funzione che viene eseguita in risposta a quell'evento. Per esempio:
  • const button = document.querySelector("button");
    
    button.addEventListener("click", () => {
      console.log("Button was clicked!");
    });
    

  • Una promessa rappresenta il risultato di un'operazione asincrona e può essere risolta (riuscito) o rifiutata (fallita), proprio come le promesse della vita reale; quando fai una promessa o la mantieni (risolvi) oppure no (rifiuti).
    Le promesse possono essere utilizzate per semplificare il processo di concatenamento delle operazioni asincrone. Per esempio:
  • const promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("Completed Async Task");
      }, 1000);
    });
    
    promise.then((result) => {
      console.log(result);
    });
    // Output: "Async task completed" (after 1 second)
    

  • Async/await: una funzionalità di JavaScript che consente l'uso della sintassi async/await per far apparire il codice asincrono e comportarsi come codice sincronizzato. Async/await si basa sulle promesse e semplifica l'utilizzo del codice asincrono.
  • async function greet(name) {
      return `Hello, ${name}!`;
    }
    
    async function main() {
      const greeting = await greet("John");
      console.log(greeting);
    }
    
    main();
    // Output: "Hello, John!"
    

Nel complesso, la programmazione asincrona consente l'esecuzione di più attività mantenendo la natura a thread singolo del linguaggio. Consente un programma più reattivo ed efficiente consentendo al thread principale di continuare a funzionare in attesa del completamento di altre attività.

Se ti piace questo contenuto non esitare a seguirci. Ci sono molti altri progetti a portata di mano di cui ho intenzione di scrivere nel prossimo futuro. Fino ad allora,

Grazie per aver letto!