用 util.promisify 模拟 bluebird.promisifyAll

Posted

技术标签:

【中文标题】用 util.promisify 模拟 bluebird.promisifyAll【英文标题】:Emulating bluebird.promisifyAll with util.promisify 【发布时间】:2018-01-15 21:41:22 【问题描述】:

我正在尝试使用 Node 8 的 util.promisify 以类似于 Bluebird 的 promisifyAll() 的工作方式来承诺整个 node_redis RedisClient 对象,但运气不佳。

这是我迄今为止尝试过的:

import * as _redis from 'redis';
import  promisify  from 'util';
const client = _redis.createClient();
const redis = Object.keys(client).reduce((c, key) => 
  if (typeof c[key] === 'function') c[key] = promisify(c[key]).bind(c);
  return c;
, client);

但是,这有效:

const redis = 
  get: promisify(client.get).bind(client),
  set: promisify(client.set).bind(client),
  hget: promisify(client.hget).bind(client),
  hmset: promisify(client.hmset).bind(client),
;

有什么想法吗?

编辑: 我想使用 util.promisify 而不是像 Bluebird 这样的东西的主要原因是因为我在 TypeScript 中做这一切,而 Bluebird 的 promisifyAll 似乎没有使用它。

【问题讨论】:

这应该有助于grizzlybit.info/2017/09/29/Node-JS-8-Util-Promisify @zubair1024 它没有,你的博客文章与我的实际问题无关。 ?????? 这是一个使用util.promisify()promisifyAll()的实现:npmjs.com/package/util-promisifyall 【参考方案1】:

您可以使用fluentify,它很小,没有外部依赖项,几乎可以满足您的需求。我实际上已经将它自己用于 Redis,有一些小警告,但在你的情况下应该相当简单,例如

import * as _redis from 'redis';
import fluentify from 'fluentifyjs';
...
const client = fluentify(_redis.createClient());
const result = await client.get('key').done();

我知道您可能希望在本地执行此操作,但是,考虑到如果需要,您可以免费获得方法链接,因此认为作为替代方案值得一提。

免责声明 - 我是作者

【讨论】:

它在 TypeScript 中能用吗?在拥有定义文件和能够将函数签名传回智能感知方面?我想使用本机 util.promisify 的一个重要原因是它可以很好地与 TypeScript 配合使用。 @aendrew 不幸的是没有,尽管添加支持不会太难。认为 lib 只需要添加定义文件,我不使用 TypeScript,所以目前还不能这样做。如果您愿意添加支持,请随时创建 PR。【参考方案2】:

我在寻找同样的东西时遇到了这个。这是我目前正在使用的,它似乎工作:

const  promisify  = require('util')
const redis = require('redis')

const client = redis.createClient('redis://localhost:6379')

client.promise = Object.entries(redis.RedisClient.prototype)
  .filter(([_, value]) => typeof value === 'function')
  .reduce((acc, [key, value]) => (
    ...acc,
    [key]: promisify(value).bind(client)
  ), )

client.on('connect', async () => 
  await client.promise.set('foo', 'bar')

  console.log(await client.promise.get('foo'))
)

【讨论】:

这很好用,但对于任何使用 typescript 的人来说都是一个小补充:将过滤器和 reduce 组合成这样的东西:reduce((acc, [key, val]) => (typeof val === 'function' ? ( ...acc, [key]: promisify(val).bind(client) ) : acc), )。否则 typescript 对promisify(value) 不满意。 你还需要对类型进行一些时髦的玩弄,我最终得到了一个接口文件,它重新实现了许多 Redis 类型(在此处找到 github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/… )以使它们返回承诺。【参考方案3】:

我尝试了以下模块,它使用起来非常简单,可以用来替换 bluebird promises。 link

https://www.npmjs.com/package/util-promisifyall

【讨论】:

以上是关于用 util.promisify 模拟 bluebird.promisifyAll的主要内容,如果未能解决你的问题,请参考以下文章

将 node-redis 与 node 8 util.promisify 一起使用

_util.default.promisify不是使用Node 9.5的函数

Promise--实践练习之fs模块 & node运行Js脚本 & Promise封装练习-fs模块 & util.promisify方法

在非回调函数上调用promisify():节点中的“有趣”结果。为什么?

Return 似乎没有在等待 javascript

node.js在控制台上获得批量输出