Guide Development Guide

What is fibjs?

fibjs is an application server development framework designed mainly for web back-end development. It is based on the Google v8 JavaScript engine and chooses a concurrent solution different from the traditional callback. fibjs uses fiber to isolate the business complexity caused by asynchronous calls at the framework layer, which greatly reduces the difficulty of development and reduces the performance problems caused by frequent asynchronous processing in user space.

Due to historical reasons, JavaScript is mainly used for browser UI processing. UI development is a typical single-threaded event-driven model. Therefore, JavaScript has also formed a programming paradigm with asynchronous processing as the main programming paradigm.

With the success of JavaScript, more and more people begin to apply JavaScript to other scenarios. At the same time, people increasingly find that asynchronous processing is not the most appropriate choice in many scenarios.

Back to basics, agile development

fibjs uses fiber in the framework layer to isolate the business complexity caused by asynchronous calls, and encapsulates the asynchronous processing of io into a more intuitive synchronous call. Engineers only need to write code in accordance with the usual synchronous business logic to enjoy the benefits of asynchronous processing. Great convenience.

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 32
conn.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, to complete the same work, the code is as follows:

1 2 3 4 5 6
conn.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 are looking for brevity, you can even write the code like this:

1 2 3 4
conn.trans(() => conn.execute('INSERT INTO log SET data=?', 'Post ' + conn.execute('INSERT INTO posts SET title=?', title).insertId + ' added')); console.log('success!');

We can clearly compare the differences brought about by two different programming styles. Less code will bring fewer errors. As the code decreases, the logic of the code is clearer. Both development and maintenance will benefit from it.

Embrace high energy

Although we can easily increase the response speed by expanding the server, performance should still be one of the important basis for choosing a development framework. With the introduction of ES7, async was introduced into JavaScript as a new asynchronous development model. However, when we enjoy the synchronization style brought by async, we also have to face its impact on performance.

We can use a piece of test code to compare the performance differences brought about by different programming styles:

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 39
var 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 results of this code are as follows:

1 2 3
async: 0.539ms callback: 0.221ms sync: 0.061ms

We can clearly know from the test results that when async is widely used in the project, the server will spend a lot of time processing async function calls and returns. We have also found this point in the actual testing of some server-side applications. And this kind of sharp drop in performance is totally unacceptable.

Because fibjs uses fiber, it can make full use of the characteristics of the JavaScript language itself and maximize the superior performance of v8. Engineers can easily maximize the performance of the server.

Flexible choice of paradigm without being kidnapped

Choosing to use fibjs does not mean that you have to use a synchronous development style. In fact, fibjs supports any asynchronous programming paradigm you have seen, and can flexibly switch between synchronous and asynchronous styles.

Both callback and async have a fatal flaw, that is contagion. As long as a function is callback or async, all other functions that depend on it must be callback or async. This will bring huge development costs in large-scale software development.

Take a simple server development scenario as an example. At the beginning of the project, we chose memory as the session data storage. At this time, we can use the sync method to directly read and store the data, and develop a complete business based on this. With the development of business scale, we need to store session data in redis or mongodb. At this time, we need to modify session-related operations to async mode.

In theory, we can modify each function in turn to make them meet the requirements of the functions they depend on, but this requires us to fully understand all modules and have the ability to modify them. This is completely impossible to accomplish when multi-person collaborative development or when using third-party modules.

Therefore, all common modules need to provide both sync and async interfaces to balance the balance between asynchrony and performance. More ordinary developers will choose to provide only the async interface. This leads to a performance disaster.

In fibjs, you can easily solve similar problems and avoid explicit asynchronous and uncontrolled infection:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
var 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 can use util.sync to convert callback or async functions into sync functions and call them directly. In this way, we can easily integrate modules of different programming paradigms, and convert them to sync paradigms with minimal development costs, effectively avoiding the disasters caused by paradigm contagion.

Start to experience

Are you ready to start a pleasant development experience? So, let's start with the installation.

👉 [ Installation and operation environment ]