Que é fibjs?
fibjs é un marco de desenvolvemento de servidor de aplicacións deseñado para o desenvolvemento de backend web. Está construído no motor JavaScript de Google V8 e usa unha solución de simultaneidade diferente á das devolucións de chamada tradicionais. fibjs usa fibra (fibra) para illar a complexidade empresarial causada polas chamadas asíncronas a nivel de marco, reducindo en gran medida a dificultade de desenvolvemento e reducindo os problemas de rendemento causados polo procesamento asincrónico frecuente no espazo do usuario.
Por razóns históricas, JavaScript úsase principalmente para xestionar a IU do navegador. O desenvolvemento da interface de usuario é un modelo típico dun só fío condutor por eventos, polo que JavaScript foi formando gradualmente o procesamento asíncrono como paradigma de programación principal.
Co éxito de JavaScript, cada vez máis persoas comezan a aplicar JavaScript a outros escenarios. Ao mesmo tempo, a xente é cada vez máis consciente de que en moitos escenarios, o procesamento asíncrono non é a opción máis axeitada.
Retorno á natureza, desenvolvemento áxil
fibjs usa fibra (fibra) a nivel de marco para illar a complexidade empresarial causada polas chamadas asíncronas e encapsula o procesamento de E/S asíncronos en chamadas síncronas máis intuitivas. Os enxeñeiros só precisan escribir código segundo a lóxica empresarial sincrónica habitual e gozar da gran comodidade que ofrece o procesamento asíncrono.
O seguinte código está tomado da documentación do módulo 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!');
});
});
});
});
En fibjs, faise o mesmo traballo, o código é o seguinte:
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 buscas simplicidade, incluso podes escribir o código deste xeito:
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!');
A través da comparación, podemos ver claramente as diferenzas traídas polos diferentes estilos de programación. Menos código significa menos erros, e con menos código, a lóxica do código faise máis clara. Neste caso, beneficiaranse tanto os traballos de desenvolvemento como de mantemento.
Abraza a alta enerxía
Aínda que é relativamente fácil escalar un servidor para mellorar a capacidade de resposta, o rendemento segue sendo unha das consideracións importantes á hora de escoller un marco de desenvolvemento. Coa introdución de ES7, async introduciuse en JavaScript como un novo modelo de desenvolvemento asíncrono. Non obstante, mentres gozamos do estilo de programación sincrónica que ofrece async, tamén debemos afrontar o seu impacto no rendemento.
Para comparar as diferenzas de rendemento traídas polos diferentes estilos de programación, podemos usar o seguinte código de proba:
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();
Baixo a versión 8 máis recente, os resultados de execución deste código son os seguintes:
1
2
3async: 0.539ms
callback: 0.221ms
sync: 0.061ms
A partir dos resultados das probas, podemos ver claramente que cando a sincronización é amplamente utilizada, o servidor pasará moito tempo procesando as chamadas e as devolucións das funcións asíncronas. Tamén atopamos isto nalgunhas probas reais de aplicacións no servidor. Non obstante, esta caída drástica do rendemento é completamente inaceptable.
Pola contra, fibjs usa tecnoloxía de fibra, aproveita ao máximo as características da propia linguaxe JavaScript e maximiza o rendemento superior do motor V8. Os enxeñeiros poden maximizar facilmente o rendemento do servidor.
Elixe paradigmas con flexibilidade sen ser secuestrado
Escoller usar fibjs non significa que teñas que usar un estilo de desenvolvemento sincrónico. De feito, fibjs admite varios paradigmas de programación asíncrona cos que estea familiarizado e pode cambiar de forma flexible entre estilos sincrónicos e asíncronos.
Non obstante, tanto se son funcións de devolución de chamada como asincrónicas, teñen un fallo fatal, que é a contaxiosidade. Se unha función é unha función de devolución de chamada ou asíncrona, todas as outras funcións que dependen dela tamén deben ser funcións de devolución de chamada ou asíncrona. No desenvolvemento de software a gran escala, isto suporá custos de desenvolvemento enormes.
Tome como exemplo un escenario sinxelo de desenvolvemento de servidores. Ao comezo do proxecto, optamos por almacenar os datos da sesión na memoria. Neste momento, podemos ler e almacenar directamente os datos mediante a sincronización e desenvolver funcións empresariais completas en función desta. A medida que a escala empresarial se expande, necesitamos almacenar os datos da sesión en Redis ou MongoDB. Neste momento, necesitamos cambiar as operacións relacionadas coa sesión ao modo asíncrono.
En teoría, podemos modificar cada función unha a unha para que se axusten aos requisitos das funcións dependentes, pero isto esixe que comprendamos completamente todos os módulos e teñamos a capacidade de modificalos. Isto é case imposible cando varias persoas están a desenvolverse en colaboración ou usando módulos de terceiros.
Polo tanto, en todos os módulos comúns, deberían proporcionarse interfaces tanto síncronas como asíncronas para equilibrar a relación entre a asincronía e o rendemento. Os desenvolvedores normais adoitan optar por proporcionar só interfaces asíncronas, o que provoca problemas de rendemento.
En fibjs pode resolver problemas semellantes facilmente e evitar a propagación incontrolada de asíncrono explícito:
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 proporciona a función util.sync, que pode converter funcións de devolución de chamada ou funcións asíncronas en funcións síncronas e chamalas directamente. Deste xeito, podemos integrar facilmente módulos de diferentes paradigmas de programación e minimizar os custos de desenvolvemento, transformándoos en paradigmas sincronizados, evitando de forma efectiva o desastre provocado polo contaxio de paradigmas.
Comeza a experimentar
Estás preparado para ter unha gran experiencia de desenvolvemento? Entón, imos comezar coa instalación.