使用promisify的节点回调样式? “'原始'参数必须是类型函数”
我在Google Cloud Function中使用util.promisify
来调用IBM Watson Text-to-Speech,它返回一个回调函数。我的代码有效,但收到错误消息:
TypeError [ERR_INVALID_ARG_TYPE]: The "original" argument must be of type function
documentation说
采用常见的错误优先回调样式的函数,即将
(err, value) => ...
回调作为最后一个参数,并返回返回promises的版本。
IBM Watson回调很复杂,我无法弄清楚如何将它重构为Node.js回调样式。它工作正常,我应该忽略错误信息吗?这是我的Google云功能:
exports.IBM_T2S = functions.firestore.document('Users/{userID}/Spanish/IBM_T2S_Request').onUpdate((change) => {
let word = change.after.data().word;
let wordFileType = word + '.mp3';
function getIBMT2S(word, wordFileType) {
const {Storage} = require('@google-cloud/storage');
const storage = new Storage();
const bucket = storage.bucket('myProject.appspot');
const file = bucket.file('Audio/Spanish/Latin_America/' + wordFileType);
var util = require('util');
var TextToSpeechV1 = require('watson-developer-cloud/text-to-speech/v1');
var textToSpeech = new TextToSpeechV1({
username: 'groucho',
password: 'swordfish',
url: ''
});
var synthesizeParams = {
text: word,
accept: 'audio/mpeg',
voice: 'es-LA_SofiaVoice',
};
const options = { // construct the file to write
metadata: {
contentType: 'audio/mpeg',
metadata: {
source: 'IBM Watson Text-to-Speech',
languageCode: 'es-LA',
gender: 'Female'
}
}
};
textToSpeech.synthesize(synthesizeParams).on('error', function(error) {
console.log(error);
}).pipe(file.createWriteStream(options))
.on('error', function(error) {
console.error(error);
})
.on('finish', function() {
console.log("Audio file written to Storage.");
});
};
var passGetIBMT2S = util.promisify(getIBMT2S(word, wordFileType))
passGetIBMT2S(word, wordFileType)
});
回答如下:
它正在工作,因为你正在调用getIBMT2S
并将返回值传递给util.promisfy
而不是函数本身。
这里有几个问题,首先你的getIBMT2S
函数看起来不像它与util.promisfy
兼容,正如你从文档中突出显示的那样,兼容函数应遵循典型的回调式签名(getIBMT2S
不需要回调参数)。
其次,util.promisify
期待一个function
- 在你的情况下,你传递函数的返回值。如果更新getIBMT2S
以支持回调参数,那么正确的用法就是
function getIBMT2S(word, wordFileType, cb) {
...
// be sure to invoke cb in here
}
var passGetIBMT2S = util.promisify(getIBMT2S); // <-- don't call getIBMT2S, pass it in directly
passGetIBMT2S(word, wordFileType) // <-- now invoke the wrapped function
.then(result => console.log('DONE'));
.catch(e => console.error(e));