10

介绍 Node.js 未来两处很不错的新特性

 3 years ago
source link: https://zhuanlan.zhihu.com/p/33689191
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

介绍 Node.js 未来两处很不错的新特性

JavaScript话题下的优秀回答者

一、Promise 化的 fs API

就在几天前 Node.js 主干合入了一个巨大的 PR:

fs: add promises API by jasnell · Pull Request #18297 · nodejs/node​github.com图标

这个 PR 实验性地加入了 Promise 化的 fs API。虽然现在我们可以使用 util.promisify 来简单地封装 fs 这一套 API,但这只是“封装”。从 Node.js 内核层面上支持 Promise 会有更大的性能优势。

以后我们可以这样优雅的读取文件:

const { readFile } = require('fs').promises

async function readAndPrint(filename) {
    console.log(await readFile(filename))
}
readAndPrint('file')
 

错误处理也可以直接使用 try...catch 了,而不是用 Promise.catch

const { readFile } = require('fs').promises

try {
    await readFile('file')
} catch(e) {
    console.log(e)
}
 

二、支持 Async Iterators 的 stream API

Async Iterators 目前已经进入 stage-3 阶段,未来将会进入语言标准,V8 目前已经支持这个语言特性。先简单介绍一下 Async Iterators(异步迭代器)是什么。

ES6 的 Generator 函数大部分人应该都或多或少知道一些:

function* idMaker() {
    var index = 0;
    while(true)
        yield index++;
}

var gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
// ...

简单地说,如果我们在 Generator 每次 yield 出的都是一个 Promise,那么它就成为了一个 Async Iterators:

function* asyncIdMaker() {
    var index = 0;
    while(true)
        yield Promise.resolve(index++);
} 

(关于 Generator 和 Iterator 的关系,可以参考这里)

针对 Async Iterators,可以使用专门的 for await 语法来操作:

for await (const id of asyncIdMaker()) {
    console.log(id)
} 

Node.js 的 stream API 在今年年初也实验性地加入了这个特性:

stream: added experimental support for for-await by mcollina · Pull Request #17755 · nodejs/node​github.com图标

在过去,我们使用 stream API 时一般都会写出类似这样的代码:

// 创建一个 stream
var myReadStream = fs.createReadStream('filename', 'utf-8')

// 响应 data 事件
myReadStream.on('data', function(chunk) {
    console.log(chunk);
    // 处理 chunk
}) 

这种基于事件回调的实现其实是不太优雅的,逻辑只要稍微复杂一些就很容易写出嵌套层次很深的代码。

现在我们可以使用 Async Iterators 这个新特性来处理:

// 创建一个 stream
var myReadStream = fs.createReadStream('filename', 'utf-8');

(async () => {
    for await (const chunk of myReadStream) {
        console.log(chunk);
        // 处理 chunk
    } 
})()

这样就减少了很多不必要的函数嵌套,并且让代码看起来更“同步”。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK