Cos'è il fibj?
fibjs è un framework di sviluppo di server di applicazioni progettato per lo sviluppo di backend web. È basato sul motore JavaScript di Google V8 e utilizza una soluzione di concorrenza diversa rispetto ai callback tradizionali. fibjs utilizza la fibra (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.
Per ragioni storiche, JavaScript viene utilizzato principalmente per gestire l'interfaccia utente del browser. Lo sviluppo dell'interfaccia utente è un tipico modello basato su eventi a thread singolo, quindi JavaScript ha gradualmente formato l'elaborazione asincrona come principale paradigma di programmazione.
Con il successo di JavaScript, sempre più persone stanno iniziando ad applicare JavaScript ad altri scenari. Allo stesso tempo, le persone sono sempre più consapevoli del fatto che in molti scenari l’elaborazione asincrona non è la scelta più appropriata.
Ritorno alla natura, sviluppo agile
fibjs utilizza la fibra (fibra) a livello di framework per isolare la complessità aziendale causata dalle chiamate asincrone e incapsula l'elaborazione I/O asincrona in chiamate sincrone più intuitive. Gli ingegneri devono solo scrivere codice secondo la consueta logica aziendale sincrona e godere della grande comodità offerta dall'elaborazione asincrona.
Il seguente codice è tratto dalla documentazione del modulo mysql:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32conn.beginTransaction(err => {
if (err) {
throw err;
}
conn.query('INSERT INTO posts SET title=?', title,
(error, results, fields) => {
if (error) {
return conn.rollback(() => {
throw error;
});
}
var log = 'Post ' + results.insertId + ' added';
conn.query('INSERT INTO log SET data=?', log,
(error, results, fields) => {
if (error) {
return conn.rollback(() => {
throw error;
});
}
conn.commit((err) => {
if (err) {
return conn.rollback(() => {
throw err;
});
}
console.log('success!');
});
});
});
});
In fibjs si fa lo stesso lavoro, il codice è il seguente:
1
2
3
4
5
6conn.trans(() => {
var result = conn.execute('INSERT INTO posts SET title=?', title);
var log = 'Post ' + results.insertId + ' added';
conn.execute('INSERT INTO log SET data=?', log);
});
console.log('success!');
Se stai cercando la semplicità, puoi anche scrivere il codice in questo modo:
1
2
3
4conn.trans(() => conn.execute('INSERT INTO log SET data=?',
'Post ' + conn.execute('INSERT INTO posts SET title=?', title).insertId +
' added'));
console.log('success!');
Attraverso il confronto, possiamo vedere chiaramente le differenze apportate dai diversi stili di programmazione. Meno codice significa meno errori e con meno codice la logica del codice diventa più chiara. In questo caso, ne trarranno beneficio sia il lavoro di sviluppo che quello di manutenzione.
Abbraccia l'alta energia
Sebbene sia relativamente semplice ridimensionare un server per migliorare la reattività, le prestazioni rappresentano ancora una delle considerazioni più importanti nella scelta di un framework di sviluppo. Con l'introduzione di ES7, l'asincrono è stato introdotto in JavaScript come nuovo modello di sviluppo asincrono. Tuttavia, se da un lato apprezziamo lo stile di programmazione sincrono offerto da async, dall’altro dobbiamo anche affrontare il suo impatto sulle prestazioni.
Per confrontare le differenze di prestazioni apportate dai diversi stili di programmazione, possiamo utilizzare il seguente codice di test:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39var count = 1000;
async function test_async(n) {
if (n == count)
return;
await test_async(n + 1);
}
function test_callback(n, cb) {
if (n == count)
return cb();
test_callback(n + 1, () => {
cb();
});
}
function test_sync(n) {
if (n == count)
return;
test_sync(n + 1);
}
async function test() {
console.time("async");
await test_async(0);
console.timeEnd("async");
console.time("callback");
test_callback(0, () => {
console.timeEnd("callback");
});
console.time("sync");
test_sync(0);
console.timeEnd("sync");
}
test();
Nell'ultima versione v8, i risultati in esecuzione di questo codice sono i seguenti:
1
2
3async: 0.539ms
callback: 0.221ms
sync: 0.061ms
Dai risultati del test, possiamo vedere chiaramente che quando l'asincrono è ampiamente utilizzato, il server impiegherà molto tempo a elaborare le chiamate e i ritorni delle funzioni asincrone. Lo abbiamo riscontrato anche in alcuni test reali delle applicazioni lato server. Tuttavia, questo drastico calo delle prestazioni è del tutto inaccettabile.
Al contrario, fibjs utilizza la tecnologia della fibra, sfrutta appieno le caratteristiche del linguaggio JavaScript stesso e massimizza le prestazioni superiori del motore V8. Gli ingegneri possono facilmente massimizzare le prestazioni del server.
Scegliere con flessibilità i paradigmi senza lasciarsi rapire
Scegliere di utilizzare fibjs non significa dover utilizzare uno stile di sviluppo sincrono. In effetti, fibjs supporta vari paradigmi di programmazione asincrona con cui hai familiarità e può passare in modo flessibile dallo stile sincrono a quello asincrono.
Tuttavia, che si tratti di funzioni di callback o asincrone, hanno un difetto fatale, ovvero la contagiosità. Se una funzione è una funzione di callback o asincrona, anche tutte le altre funzioni che dipendono da essa devono essere funzioni di callback o asincrone. Nello sviluppo di software su larga scala, ciò comporterà enormi costi di sviluppo.
Prendiamo come esempio un semplice scenario di sviluppo di un server. All'inizio del progetto abbiamo scelto di archiviare i dati della sessione in memoria, in questo momento possiamo leggere e archiviare direttamente i dati utilizzando la sincronizzazione e su questa base sviluppare funzioni aziendali complete. Man mano che la scala aziendale si espande, dobbiamo archiviare i dati della sessione in Redis o MongoDB. Al momento, dobbiamo modificare le operazioni relative alla sessione in modalità asincrona.
In teoria, possiamo modificare ciascuna funzione una per una per renderla conforme ai requisiti delle funzioni dipendenti, ma ciò richiede di comprendere appieno tutti i moduli e di avere la capacità di modificarli. Ciò è quasi impossibile quando più persone sviluppano in modo collaborativo o utilizzano moduli di terze parti.
Pertanto, in tutti i moduli comuni, dovrebbero essere fornite sia interfacce sincrone che asincrone per bilanciare la relazione tra asincronia e prestazioni. Gli sviluppatori ordinari solitamente scelgono di fornire solo interfacce asincrone, causando problemi di prestazioni.
In fibjs puoi facilmente risolvere problemi simili ed evitare la propagazione incontrollata di asincrono esplicito:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17var util = require('util');
function session_get(sid) {
return sdata;
}
async function async_session_get(sid) {
return sdata;
}
function callback_session_get(sid, cb) {
cb(null, sdata);
}
data = session_get(sid);
data = util.sync(async_session_get)(sid);
data = util.sync(callback_session_get)(sid);
fibjs fornisce la funzione util.sync, che può convertire funzioni di callback o funzioni asincrone in funzioni sincrone e chiamarle direttamente. In questo modo, possiamo facilmente integrare moduli provenienti da diversi paradigmi di programmazione e ridurre al minimo i costi di sviluppo, trasformandoli in paradigmi sincronizzati, evitando di fatto il disastro causato dal contagio dei paradigmi.
Inizia a sperimentare
Sei pronto per vivere una fantastica esperienza di sviluppo? Quindi, iniziamo con l'installazione.