2 回答

TA貢獻1825條經驗 獲得超4個贊
這里似乎同時存在幾個問題/誤解。讓我們試著一次看一次。
首先,您似乎認為外部函數(shù)將返回(“傳遞”)您的回調的返回值
正如您在庫源代碼中看到的那樣,情況并非如此。
此外,它甚至沒有意義,因為回調為每個項目調用一次。那么,對于 10 個項目,它將被調用 10 次,那么如何parseFileItems知道回調的 10 個返回值中的哪一個傳遞給外部?
從回調函數(shù)返回什么并不重要,因為該parseFileItems函數(shù)只是忽略它。此外,parseFileItems函數(shù)本身也不返回任何內容。因此,結果new pdfreader.parseFileItems(...)將始終評估為undefined(并且undefined顯然沒有屬性then)。
其次,您似乎認為這.then是函數(shù)調用的某種通用鏈接方法。
事實上,.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)分支中。你可以這樣實現(xiàn),使用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)
})
注意:使用異步生成器你會得到更好的代碼,但是現(xiàn)在在這里解釋太多了,因為從回調到異步生成器的轉換沒有你想象的那么簡單。

TA貢獻1765條經驗 獲得超5個贊
如果要鏈接 a then,則需要回調函數(shù)返回 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);
});
添加回答
舉報