为什么NodeJS不使用Promise作为readFile API?

Han*_*Sun 10 javascript asynchronous nonblocking node.js promise

https://pragprog.com/book/tbajs/async-javascript这本书中,我发现了这个:

Node的早期迭代在其非阻塞API中使用了Promises.然而,在2010年2月,Ryan Dahl做出了切换到现在熟悉的回调(错误,结果......)格式的决定,理由是Promises是属于"userland"的更高级别的构造.

它看起来很混乱,因为作为读取文件的API,这个

fs.readFile('/etc/passwd')
.onSuccess(function(data){console.log(data)})
.onError(function(err){throw err})
Run Code Online (Sandbox Code Playgroud)

看起来比这更好:

fs.readFile('/etc/passwd', function (err, data) {
  if (err) throw err;
  console.log(data);
});
Run Code Online (Sandbox Code Playgroud)

有没有人知道为什么"Promise是一个更高级别的构造"会阻止自己在NodeJS API中使用?

Ben*_*aum 15

Node v8附带了util.promisify将回调API转换为promises,Node v10附带本机promises支持(实验性):

const fs = require('fs').promises;

// in an async function:
let data = await fs.readFile('/etc/passwd');
console.log(data);
Run Code Online (Sandbox Code Playgroud)

未来是承诺:

NodeJS 使用新API的promises.事实上,目前正在讨论如何.由于摩擦和性能问题,多年前在节点中使用Promise的早期尝试失败了.

首先要做的是:

现在promises是一种本地语言功能,但必须在它们进入核心API之前发生:

  • 承诺必须是已经发生的本地语言构造.
  • 最近宣布的NodeJS和io.js合并必须发生 - 时间框架可能是短短几个月.
  • v8(JavaScript引擎)团队必须完成私有符号的处理,这将实现快速承诺的创建.目前,promise构造函数是在本机promises中创建promise的唯一方法,它分配了一个相对昂贵的闭包.目前正在使用Domenic在io.js和v8团队之间紧密协调,以确保正确完成.
  • v8团队必须优化承诺实现,目前本机承诺会像bluebird一样失去用户端实现.这也正在发生.

一旦发生所有这些,API将被分叉,并且包含promises的版本将被集成到核心中.这是一个漫长而无趣的讨论 - 在io.js/NG回购中有一个更好的讨论,但两者都没有太多的信息.

今天可以做些什么

这样的库为您提供了一种工具,可以快速有效地将回调API转换为承诺.您今天可以使用它们并获得该功能.


ber*_*ing 5

从历史上看,由于性能原因,回调是默认的,但是...

2017年更新/节点8:核心现在支持承诺!

自Node v8.x起,Node.js支持Promise。这些API仍然都是用回调样式编写的(以实现向后兼容性等),但是节点核心中现在有一个实用程序类,可将基于回调的API转换为基于Promise的API(类似于bluebird):

https://nodejs.org/api/util.html#util_util_promisify_original

从Node.js文档中:

例如:

const util = require('util');
const fs = require('fs');

const stat = util.promisify(fs.stat);
stat('.').then((stats) => {
  // Do something with `stats`
}).catch((error) => {
  // Handle the error.
});
Run Code Online (Sandbox Code Playgroud)

或者,等效地使用异步函数:

const util = require('util');
const fs = require('fs');

const stat = util.promisify(fs.stat);

async function callStat() {
  const stats = await stat('.');
  console.log(`This directory is owned by ${stats.uid}`);
}
Run Code Online (Sandbox Code Playgroud)