Sincrono e asincrono
introduzione
Poiché le applicazioni Web continuano a svilupparsi, anche JavaScript, in quanto linguaggio di programmazione ampiamente utilizzato, è in costante sviluppo ed evoluzione. Nello sviluppo front-end Web, JavaScript viene utilizzato principalmente per l'elaborazione dell'interfaccia utente del browser. Lo sviluppo dell'interfaccia utente è un tipico modello basato su eventi a thread singolo, quindi JavaScript ha anche formato un paradigma di programmazione con l'elaborazione asincrona come paradigma di programmazione principale. Tuttavia, nelle applicazioni complesse e su larga scala, i problemi e la complessità causati dalla programmazione asincrona stanno diventando sempre più evidenti.
L'emergere di Node.js porta un nuovo paradigma di programmazione asincrona in JavaScript: loop di eventi e funzioni di callback. Questo paradigma di programmazione è efficiente e conciso ed è adatto a scenari con concorrenza elevata e uso intensivo di I/O. Tuttavia, questo paradigma di programmazione comporta anche problemi e complessità: soprattutto in applicazioni complesse e su larga scala, i programmatori devono affrontare il problema di annidare molte funzioni di callback e devono affrontare il problema dell'ordine di chiamata asincrono, che aumenta la complessità. e la difficoltà del programma.
Per risolvere questi problemi e difficoltà è nato fibjs. fibjs è un framework di sviluppo di server di applicazioni progettato principalmente per lo sviluppo di back-end Web. Si basa sul motore JavaScript di Google v8 e sceglie una soluzione di concorrenza diversa rispetto al tradizionale callback. fibjs utilizza la fibra per isolare la complessità aziendale causata dalle chiamate asincrone a livello di framework, riducendo notevolmente la difficoltà di sviluppo e riducendo i problemi di prestazioni causati dalla frequente elaborazione asincrona nello spazio utente. Allo stesso tempo, rispetto al tradizionale paradigma di programmazione asincrona, il suo paradigma di programmazione sincrona presenta i vantaggi di maggiore leggibilità, logica semplice e facile manutenzione.
Nel contenuto seguente presenteremo i vantaggi e le caratteristiche di fibjs e spiegheremo come utilizzare le sue soluzioni di programmazione sincrona e asincrona attraverso esempi.
introduzione delle fibre
fibjs è un framework server JavaScript ad alte prestazioni basato sul motore v8, principalmente per lo sviluppo back-end Web. Avviato nel 2009, ha già un'elevata stabilità e produttività e ha una vasta gamma di casi applicativi in patria e all'estero.
In fibjs, la fibra viene utilizzata per risolvere il problema tra la logica aziendale e l'elaborazione I/O. La fibra è diversa dai concetti tradizionali come thread, coroutine e processi: è un thread leggero a livello utente che può essere considerato un meccanismo multitasking cooperativo. La fibra può eseguire operazioni logiche di business e I/O in diversi contesti e gestire le risorse internamente attraverso la pre-allocazione e il riciclo. Rispetto ai thread e ai processi tradizionali, è più leggera, più flessibile e più efficiente.
Rispetto ad altre librerie di thread (come pthread, WinThread, Boost.Thread, ecc.), la fibra presenta i seguenti vantaggi:
Scheduling collaborativo : Fiber è uno scheduling collaborativo che non richiede una scheduling preventiva da parte del kernel o del sistema operativo. Riduce i frequenti cambi di contesto, accelera la velocità di esecuzione del programma ed evita condizioni di concorrenza e problemi di stallo tra i thread.
Leggero : ogni fibra consuma solo un piccolo spazio nello stack ed è possibile creare un gran numero di fibre in applicazioni multi-concorrenti senza causare il problema di occupare troppa memoria.
Efficienza : la fibra è implementata in base alle caratteristiche del linguaggio JavaScript stesso, e sfrutta appieno le prestazioni superiori del motore v8, che è più veloce delle tradizionali librerie di thread.
Utilizzando la fibra, fibjs può separare la logica aziendale e l'elaborazione I/O, incapsulando così le chiamate asincrone sotto forma di chiamate sincrone, rendendo la scrittura e la manutenzione del codice più semplice e facile da leggere e, allo stesso tempo, sfruttando appieno i vantaggi della fibra. Linguaggio JavaScript.
Programmazione sincrona in fibjs
Nella programmazione asincrona, l'annidamento delle funzioni di callback può portare a una scarsa leggibilità del codice, causare facilmente il problema dell'inferno delle callback e aumentare la difficoltà del codice e il costo del debug. Il paradigma di programmazione sincrona è più in linea con i modelli di pensiero umano, rendendo la struttura del codice più chiara, più facile da leggere e da mantenere, il che può migliorare notevolmente l'efficienza dello sviluppo e la qualità del codice.
In fibjs, la programmazione sincrona è un paradigma di programmazione molto popolare e comunemente utilizzato, che rende la struttura e la logica del codice più intuitive, facili da comprendere e mantenere. Alcune funzioni e moduli di programmazione sincrona sono altamente supportati in fibjs, come util.sync, fs.readSync, ecc.
In fibjs, puoi chiamare direttamente le funzioni asincrone degli oggetti integrati in modo sincrono:
1
2
3
4const fs = require("fs");
const data = fs.readFile("/path/to/file");
console.log(data);
Puoi anche racchiudere la funzione asincrona tramite util.sync e try...catch, in modo che la fibra possa ottenere il valore di ritorno della chiamata asincrona, ottenendo così l'effetto di sincronizzazione, ad esempio:
1
2
3
4
5
6
7
8
9
10
11
12
13// load module
const coroutine = require("coroutine");
const util = require("util");
const fs = require("fs");
// use util.sync to wrap fs.readFile
function readFile(path) {
return util.sync(fs.readFile)(path);
}
// call the sync function
const data = readFile("myfile.txt");
console.log(data);
Nell'esempio precedente, abbiamo definito una funzione denominata readFile e utilizzato util.sync per incapsulare la funzione asincrona fs.readFile in una funzione sincrona, che può restituire direttamente i dati tramite chiamate sincrone. Questo metodo di chiamata sincrona è simile al tradizionale paradigma di programmazione JavaScript, con la differenza che in fibjs il thread non è bloccato, ma l'effetto asincrono è ottenuto tramite fibra.
Come funziona util.sync
util.sync è un'efficiente funzione wrapper del kernel. Il seguente codice JavaScript può ottenere funzioni simili:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23const coroutine = require("coroutine");
function sync(func) {
return function _warp() {
var ev = new coroutine.Event();
var e, r;
func.apply(this, [
...arguments,
function (err, result) {
e = err;
r = result;
ev.set();
}
]);
ev.wait();
if (e)
throw e;
return r;
}
}
Questo codice definisce una funzione di sincronizzazione dello strumento per convertire una funzione di callback asincrona in una funzione di chiamata sincrona. Riceve una funzione func e restituisce una nuova funzione _wrap. Questa nuova funzione implementa la funzione di conversione della funzione originale in una chiamata sincrona. Nella funzione _wrap, viene prima creato un nuovo oggetto Evento ev per la pianificazione dei thread e l'attesa dei risultati del callback asincrono. Quindi utilizzare il metodo apply per chiamare la funzione originale func con i parametri specificati e una nuova funzione di callback come parametri. Durante il processo di chiamata, si verifica un callback asincrono e la nuova funzione di callback memorizza i risultati restituiti nelle variabili e e r e riattiva l'oggetto Event. Infine, si decide in base alla variabile e se lanciare un'eccezione o restituire la variabile r. Questa funzione implementa una soluzione per convertire le funzioni di callback asincrone in chiamate sincrone, che possono migliorare la leggibilità e la manutenibilità della funzione.
Programmazione asincrona in fibjs
In fibjs, la maggior parte dei metodi asincroni (compresi i metodi di I/O e di richiesta di rete, ecc.) possono supportare sia chiamate sincrone che asincrone, il che consente agli sviluppatori di scegliere in qualsiasi momento quale metodo utilizzare in base alle proprie esigenze di programmazione.
Prendendo fs.readFile() come esempio, possiamo utilizzare questo metodo in due modi:
Metodo asincrono: elabora il risultato della lettura del file passando una funzione di callback, ad esempio:
1
2
3
4
5
6const fs = require("fs");
fs.readFile("/path/to/file", (err, data) => {
if (err) throw err;
console.log(data);
});
Questo metodo è adatto per situazioni in cui è necessario eseguire alcune operazioni dopo aver letto il file.
Metodo sincrono: ottieni il contenuto del file non passando una funzione di callback, ad esempio:
1
2
3
4const fs = require("fs");
const data = fs.readFile("/path/to/file");
console.log(data);
In questo esempio, otteniamo il contenuto del file leggendo i dati del valore restituito dal file. Non è necessario attendere che la funzione di callback completi la lettura del file prima di continuare l'operazione. Questo metodo è adatto per situazioni in cui è necessario eseguire alcune operazioni prima che la lettura del file sia completata.
Si può vedere che questa funzionalità di supportare chiamate sia sincrone che asincrone consente agli sviluppatori di scegliere di utilizzare metodi diversi in base alle proprie esigenze e agli scenari di sviluppo. In alcuni casi, il codice sincrono è più leggibile e più facile da gestire ed eseguire il debug; mentre in alcuni casi, il codice asincrono può migliorare meglio la velocità di risposta e le prestazioni del codice.
Tuttavia, è necessario fare attenzione quando si utilizza il metodo di sincronizzazione: in alcuni scenari, questo metodo potrebbe bloccare la fibra corrente. Pertanto, dobbiamo scegliere il metodo di programmazione appropriato in base alle esigenze effettive.
Insomma
In questo articolo presentiamo lo stile di programmazione sincrona e le soluzioni di programmazione asincrona di fibjs, nonché i loro vantaggi e scenari applicativi. Abbiamo accennato al fatto che fibj può ridurre la complessità operativa e migliorare l'efficienza dello sviluppo del codice utilizzando la fibra per isolare la logica aziendale e i problemi di prestazioni causati dall'elaborazione asincrona. Allo stesso tempo, abbiamo anche sottolineato i vantaggi di fibjs nell'elaborazione I/O e nella gestione della memoria, il che apporta grande comodità allo sviluppo, al test e alla manutenzione.
Infine, incoraggiamo i lettori a esplorare fibjs in profondità e a partecipare ai contributi di fibjs e alle attività della comunità. Crediamo che fibjs continuerà ad attirare l'attenzione e il supporto della comunità open source con le sue potenti prestazioni e la sua facilità d'uso.