Original:
New io.js FeaturesThe
io.js platform
is developing at a fast pace, having a great impact on the entire Node ecosystem. In a short time, many fixes have been made to io.js, performance has been improved, and new features and functions have been added.
If you have not followed the development of io.js, do not worry - in this article we will briefly present the main features of the platform. We will consider them as they are released, that is, from the old to the new. Where it will be necessary, we will give links to the relevant documentation (in English). Describing each new functionality, we will indicate its first version. The code is written using standard ES6 functions that are available in io.js. So, let's begin…
')
ES6 features (1.0.0)
Initially, one of the tasks of the io.js developers was to get closer to the functionality of the V8, namely: to fully utilize all the existing features of ES6. It was believed that the built-in default generators, as well as other
functions of ES6 , will work quite stably and without flags. We advise you not to rush to search for information on ES6 - first read the documentation, links to which we will give in the article.
Documentation Link:
ES6 FeaturesNote : By default, some functions of ES6 are present in Node 0.12. Under the --harmony flag you can find even more features. However, the operation and availability of ES6 features is different from io.js (for example: node-generators are not present by default in the Node).
Detailed Error Documentation (1.2.0)
Ever wondered what is EPIPE, EMFILE, ENOENT? I personally asked myself this question more than once. Thank God, now in io.js there is a much improved documentation on errors.
Documentation Link:
Error DocumentationSimple threading implementation (1.2.0)
Formally, when it is necessary to apply a stream, you expand the base stream and apply one or several methods, depending on the type of stream. For example, the Transform stream assumes the use of the _transform method and the _flush method optionally. In the example below, you can see how the Stream stream splits the file in rows:
var stream = require('stream') var liner = new stream.Transform( { objectMode: true } ) liner._transform = function (chunk, enc, done) { var data = chunk.toString() if (this._lastLineData) { data = this._lastLineData + data } var lines = data.split('\n') this._lastLineData = lines.splice(lines.length-1,1)[0] lines.forEach(this.push.bind(this)) done() } liner._flush = function (done) { if (this._lastLineData) { this.push(this._lastLineData) } this._lastLineData = null done() } module.exports = liner
With all the “guts” of the method out, the code looks pretty untidy. Now you can pass these methods as options to the constructor. Just remove the underscore (_). Liner allows you to change the code (using object notation from extensions in ES6) and get the following:
'use strict' const stream = require('stream') let liner = new stream.Transform({
Reference to documentation:
Stream ConstructorAbility to view all IP addresses for a domain (1.2.0)
If you registered the dns.lookup command in earlier versions of io.js, you would be given only the first address. Now there is an {all: true} option that allows you to get a whole array of addresses.
'use strict' const dns = require('dns')
Link to documentation:
About dns.lookupEvent unhandleRejection (1.4.1)
If you reject the promise, but no one will ever know about it, can we assume that it was really rejected? Of course this happened, but again - no one will know about it! As you can guess, here lies the root of the appearance of many complex errors in the code. For example, look at the code below:
'use strict' let delay = function (ms) { return new Promise(function (resolve) { setTimeout(resolve, ms) }) } delay(2000) .then(function (data) { data.foo = 'hello' })
See a mistake? The delay function returns a Promise that will be executed after a certain time, and when it is executed, we get undefined and ReferenceError. This will happen because we tried to access the foo property with a value of undefined. Meanwhile, we will never know what happened, and we will be scratching the back of our heads with surprise, because no one has paid attention to the untreated failures. Although in some libraries, the possibility of such behavior promise is registered, in ES6 you will not find information about this. Fortunately, you can check the code with the unhandledRejection event through the process.
process.on('unhandledRejection', function (er) { console.log('got unhandled rejection', er.stack) })
If you are using promise in ES6, then we recommend that you configure unhandledRejection so that no failure will go unnoticed.
Documentation link:
process.on (“unhandledRejection”)Note : There is also a rejectionHandled event. It is used when it is necessary to deal with promise rejection, which occurs in the next step of the event loop. rejectionHandled is useful when promises that were incorrectly screened out using unhandledRejection need to be reset. For a more detailed description see the
documentation .
StreamWrap and JSStream (1.4.1)
Starting from this version, between threads in C ++ and JS has appeared a full link. Now you can use the standard Duplex stream for data entry when working with low order streams (for example, with software sockets) in C ++. The tls.connect () method takes full advantage of this feature. As an example, review the following
test suite .
Buffer method # indexOf
The following describes a convenient method of how to search the buffer using a string, buffer, or number. The method behaves in the same way as Array # indexOf, namely: it returns the index of the starting position of the first match found in the buffer. Optionally, you can specify a starting index as an optional parameter.
'use strict' const assert = require('assert') let buf = new Buffer('abc def ghi') assert.equal(buf.indexOf('abc'), 0) assert.equal(buf.indexOf('bc'), 1) assert.equal(buf.indexOf('def'), 4) assert.equal(buf.indexOf('c'), 2) assert.equal(buf.indexOf('c', 4), 11)
The additional method lastIndexOf is still under discussion.
Documentation link:
buffer # indexOfPreloading Modules (1.6.0)
Now you can preload modules while running scripts or using REPL. This can be done using -r or the --require flag. For example:
iojs -r ./foo -r bar my-app.js
Same as:
require('./foo') require('bar') require('./my-app')
Preloading modules provides new options for using io.js. For example, you can add new functionality to a useful, working application. Or: You want to create an application that will take snapshots of the state of an unordered array to eliminate data leakage. To do this, you will not need to support this configuration:
if (cfg.useHeapdump) require('heapdump')
You just need to start the application with the preloaded module when you need the required functionality:
iojs -r heapdump app.js
Another use is with compilers (Babel, CoffeeScript, etc.). For example, if you use Babel to compile code on ES6 or ES7, you need to write something like this:
require('babel/register') require('./my-actual-app')
Now, you can configure directly from the command line without using the native application:
iojs -r babel/register my-actual-app.js
Note : At the moment, Babel already fully supports Node. A special tool allows you to do the above and even more.
Troubleshooting Errors with Synchronous I / O (2.1.0)
Although Synchonous I / O is convenient, especially for shell scripting, it greatly reduces the performance of many applications (for example, servers). You can search for Sync in code, but what if you use a third-party module that does not follow the naming scheme? This is where the --trace-sync-io flag comes to the rescue. When a synchronous request is executed, you are notified of the stack trace.
Let's look at a simple example:
'use strict' const http = require('http') const cp = require('child_process') http.createServer(function (req, res) { let stdout = cp.execFileSync('whoami') res.end(`${stdout}\n`) }).listen(3000)
We have an HTTP server that processes synchronous code for each request. Recommend this option is impossible. So, if we run iojs --trace-sync-io server.js and then go to httpL // localhost: 3000, we will see the following warning in the console:
WARNING: Detected use of sync API at spawnSync (child_process.js:1241:27) at execFileSync (child_process.js:1291:13) at /Users/wavded/Projects/whats-new-iojs/server.js:6:19 at emitTwo (events.js:87:13) at emit (events.js:172:7) at parserOnIncoming (_http_server.js:474:12) at parserOnHeadersComplete (_http_common.js:88:23) at socketOnData (_http_server.js:325:22) at emitOne (events.js:77:13)
A little bit of everything
Several interesting features that are worth paying attention to:
- You can write require ('./') with require ('.') (1.6.2).
- When using console.log or util.inspect, ES6, the Promise, Map and Set objects have a beautiful view (2.0.0).
- os.tmpdir () works equally well on all operating systems (2.0.0). Previously, some operating systems gave slashes, not to mention other errors. Now you will never run into this problem.
- Many other improvements: query string parsing (query string) (1.6.1), less tls memory usage (2.0.0), faster process.nextTick (2.0.0) and util.format for individual arguments (2.1.0).
- Gradual security improvements io.js. When exchanging keys using the Diffie-Hellman method, the parameters must be at least 1024 bits (2.1.0).
Where to find more information?
In my opinion the best information can be found on
ChangeLog on GitHub. Io.js also keeps an official blog on
Medium , where you can find information about the latest platform updates and the project as a whole.
Posted by: Marc Harter
Worked on the translation:
greebn9k (Sergey Gribnyak),
seninrom (Roman Senin),
silmarilion (Andrey Khakharev)
Singree