2 回答
TA贡献1825条经验 获得超4个赞
这里似乎同时存在几个问题/误解。让我们试着一次看一次。
首先,您似乎认为外部函数将返回(“传递”)您的回调的返回值
正如您在库源代码中看到的那样,情况并非如此。
此外,它甚至没有意义,因为回调为每个项目调用一次。那么,对于 10 个项目,它将被调用 10 次,那么如何parseFileItems知道回调的 10 个返回值中的哪一个传递给外部?
从回调函数返回什么并不重要,因为该parseFileItems函数只是忽略它。此外,parseFileItems函数本身也不返回任何内容。因此,结果new pdfreader.parseFileItems(...)将始终评估为undefined(并且undefined显然没有属性then)。
其次,您似乎认为这.then是函数调用的某种通用链接方法。
事实上,.then它是一种链接承诺的方式,或者对承诺的履行作出反应。在这种情况下,任何地方都没有任何承诺,特别parseFileItems是不返回承诺(它返回undefined如上所述),所以你不能调用.then它的结果。
根据文档,您应该自己对错误和流结束做出反应。因此,您的代码将像这样工作:
let pages = [];
new pdfreader.PdfReader()
.parseFileItems(pp, function(err, item) {
{
if (!item) {
// ****** Here we are done! ******
console.log("done" + pages.length) // The code that was in the `then` goes here instead
} else if (item.page) {
pages.push(lines);
rows = {};
} else if (item && item.text) {
// accumulate text items into rows object, per line
(rows[item.y] = rows[item.y] || []).push(item.text);
}
}
})
但是,我同意拥有一个 promise 包装器会更好,这样您就不必将以下所有代码填充到回调的if (!item)分支中。你可以这样实现,使用new Promise:
const promisifiedParseFileItems = (pp, itemHandler) => new Promise((resolve, reject) => {
new pdfreader.PdfReader().parseFileItems(pp, (err, item) => {
if (err) {
reject(err)
} else if (!item) {
resolve()
} else {
itemHandler(item)
}
})
})
let pages = []
promisifiedParseFileItems(pp, item => {
if (item.page) {
pages.push(lines)
rows = {}
} else if (item && item.text) {
// accumulate text items into rows object, per line
(rows[item.y] = rows[item.y] || []).push(item.text)
}
}).then(() => {
console.log("done", pages.length)
}, e => {
console.error("error", e)
})
注意:使用异步生成器你会得到更好的代码,但是现在在这里解释太多了,因为从回调到异步生成器的转换没有你想象的那么简单。
TA贡献1765条经验 获得超5个赞
如果要链接 a then,则需要回调函数返回 Promise :
new pdfreader.PdfReader()
.parseFileItems(pp, function (err, item) {
return new Promise( (resolve, reject) => {
let pages = ...
// do stuff
resolve(pages);
}
})
.then( pages => {
console.log("done" + pages.length);
});
添加回答
举报