What is fibjs?
fibjs is an application server development framework designed for web backend development. It is built on the Google V8 JavaScript engine and uses a different concurrency solution than traditional callbacks. fibjs uses fiber (fiber) to isolate the business complexity caused by asynchronous calls at the framework level, greatly reducing the difficulty of development and reducing performance problems caused by frequent asynchronous processing in user space.
For historical reasons, JavaScript is mainly used to handle browser UI. UI development is a typical single-threaded event-driven model, so JavaScript has gradually formed asynchronous processing as the main programming paradigm.
With the success of JavaScript, more and more people are beginning to apply JavaScript to other scenarios. At the same time, people are increasingly aware that in many scenarios, asynchronous processing is not the most appropriate choice.
Return to nature, agile development
fibjs uses fiber (fiber) at the framework level to isolate the business complexity caused by asynchronous calls, and encapsulates asynchronous I/O processing into more intuitive synchronous calls. Engineers only need to write code according to the usual synchronous business logic and enjoy the great convenience brought by asynchronous processing.
The following code is taken from the documentation of the mysql module:
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, the same work is done, the code is as follows:
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!');
If you're looking for simplicity, you can even write the code like this:
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!');
Through comparison, we can clearly see the differences brought by different programming styles. Less code means fewer errors, and with less code, the logic of the code becomes clearer. In this case, both development and maintenance work will benefit.
Embrace high energy
Although it is relatively easy to scale a server to improve responsiveness, performance is still one of the important considerations when choosing a development framework. With the introduction of ES7, async was introduced into JavaScript as a new asynchronous development model. However, while we enjoy the synchronous programming style brought by async, we must also face its impact on performance.
In order to compare the performance differences brought by different programming styles, we can use the following test code:
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();
Under the latest v8, the running results of this code are as follows:
1
2
3async: 0.539ms
callback: 0.221ms
sync: 0.061ms
From the test results, we can clearly see that when async is widely used, the server will spend a lot of time processing the calls and returns of async functions. We also found this in some actual server-side application tests. However, this drastic drop in performance is completely unacceptable.
In contrast, fibjs uses fiber technology, takes full advantage of the characteristics of the JavaScript language itself, and maximizes the superior performance of the V8 engine. Engineers can easily maximize server performance.
Flexibly choose paradigms without being kidnapped
Choosing to use fibjs doesn't mean you have to use a synchronous development style. In fact, fibjs supports various asynchronous programming paradigms you are familiar with, and can flexibly switch between synchronous and asynchronous styles.
However, whether they are callback functions or async, they have a fatal flaw, which is contagiousness. If a function is a callback or async function, then all other functions that depend on it must also be callback or async functions. In large-scale software development, this will result in huge development costs.
Take a simple server development scenario as an example. At the beginning of the project, we chose to store the session data in memory. At this time, we can directly read and store the data using synchronization, and develop complete business functions based on this. As the business scale expands, we need to store session data in Redis or MongoDB. At this time, we need to change session-related operations to asynchronous mode.
In theory, we can modify each function one by one to make them conform to the requirements of the dependent functions, but this requires us to fully understand all modules and have the ability to modify them. This is almost impossible when multiple people are developing collaboratively or using third-party modules.
Therefore, in all common modules, both synchronous and asynchronous interfaces should be provided to balance the relationship between asynchrony and performance. Ordinary developers usually choose to provide only asynchronous interfaces, causing performance problems.
In fibjs you can easily solve similar problems and avoid uncontrolled propagation of explicit async:
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 provides the util.sync function, which can convert callback functions or asynchronous functions into synchronous functions and call them directly. In this way, we can easily integrate modules from different programming paradigms and minimize development costs, transforming them into synchronized paradigms, effectively avoiding the disaster caused by paradigm contagion.
Start experiencing
Are you ready to have a great development experience? So, let’s start with installation.