我在这里可能确实缺少一些明显的东西,但是如何将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
有没有一种方法而无需更改功能(实际上,它是一个库函数,所以我不能)。
答案 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着袖子去做心脏直视手术,但是我很高兴我发现有人已经这样做了。
如果您使用Bluebird的Promisify
(它越来越受欢迎),那么实际上有一个{ multiArgs: true }
标记可以通过,它将在这里完全满足您的需求! (Source)
它将回调的多个参数转换为数组。因此,在我的MySQL's query情况下,默认回调具有3个参数(error, result, fields)
,典型的promisify无法获得fields
。但是,如果传递了{multiArgs: true}
标志,则解析后的值将成为[result, fields]
的数组。