NodeJ:util.promisify,其中回调函数具有多个参数

时间:2019-01-04 12:48:07

标签: node.js

我在这里可能确实缺少一些明显的东西,但是如何将util.promisify与看起来像这样的函数一起使用?

function awkwardFunction (options, data, callback) {
    // do stuff ...
    let item = "stuff message"
    return callback(null, response, item)
}

我可以这样叫:

 awkwardFunction ({doIt: true},'some data', (err, result, item) => {
      console.log('result')
      console.log(result)
      console.log('item')
      console.log(item)
      done()
    })

然后回来

result
{ data: 'some data' }
item
stuff message

使用承诺版本时:

let kptest = require('util').promisify(awkwardFunction)
kptest({doIt: true},'some data')
   .then((response, item) => {
    console.log('response')
    console.log(response)
    console.log('item')
    console.log(item)

 })
 .catch(err => {
     console.log(err)
  })

并尝试同时访问“响应”和“项目”,似乎第二个参数已被忽略...

result
{ data: 'some data' }
item
undefined

有没有一种方法而无需更改功能(实际上,它是一个库函数,所以我不能)。

5 个答案:

答案 0 :(得分:6)

util.promisify旨在与具有function (err, result): void签名的节点样式回调一起使用。

可以手动处理多个参数:

let kptest = require('util').promisify(
  (options, data, cb) => awkwardFunction(
    options,
    data,
    (err, ...results) => cb(err, results)
  )
)

kptest({doIt: true},'some data')
.then(([response, item]) => {...});

如果需要更复杂的功能,可以使用诸如pify之类的第三方解决方案代替util.promisify,它可以使用multiArgs option来解决这种情况。

答案 1 :(得分:2)

不可能有.then((response, item) => {,因为承诺代表单个价值。但是您可以像这样.then(({response, item}) => {拥有两个字段的对象。

您需要为该功能提供自定义的Promisify实现。

const { promisify } = require('util')

awkwardFunction[promisify.custom] = (options, data) => new Promise((resolve, reject) => {
  awkwardFunction(options, data, (err, response, item) => {
    if(err) { reject(err) }
    else { resolve({ response, item }) }
  })
})

const kptest = promisify(awkwardFunction)

或者,如果这是唯一一个实现了功能的地方,则可以直接使用承诺的版本const kptest = (options, data) => new Promise(...,而无需其他的实现步骤。

答案 2 :(得分:2)

您可以做出自己的承诺,在其中返回一个承诺,该承诺将使用回调的参数进行解析,然后在then块中对它们进行解构。希望这会有所帮助。

function awkwardFunction (options, data, callback) {
    // do stuff ...
    let item = "stuff message";
    return callback(null, data, item);
}

const mypromisify = (fn) =>
    (...args) =>
        new Promise(resolve =>
            fn(...args,
                (...a) => resolve(a)
            )
        );

const kptest = mypromisify(awkwardFunction);

kptest({ doIt: true }, 'some data')
    .then(([error, response, item]) => {
        console.log(response);
        console.log(item);
    })
    .catch(err => {
        console.log(err);
    });

答案 3 :(得分:0)

我无法确定我最喜欢哪种方法-所有3个答案都很棒。尤里·塔拉班科(Yury Tarabanko)可能是最“标准”的,亚历克斯·克(Alex G)的通用性很好,而发情的超级简单。

我不想将此问题保留为“未回答”,因为那是不对的,对其他寻找相同信息的人没有用。

如果有更好的解决方法,请主持人让我知道!

答案 4 :(得分:0)

我只是ling着袖子去做心脏直视手术,但是我很高兴我发现有人已经这样做了。

如果您使用BluebirdPromisify(它越来越受欢迎),那么实际上有一个{ multiArgs: true }标记可以通过,它将在这里完全满足您的需求! (Source

它将回调的多个参数转换为数组。因此,在我的MySQL's query情况下,默认回调具有3个参数(error, result, fields),典型的promisify无法获得fields。但是,如果传递了{multiArgs: true}标志,则解析后的值将成为[result, fields]的数组。

相关问题