调整不可链接的函数以返回值

我正在尝试使用pdfreader 包在一个对象中获取 pdf 的所有页面。该函数在处理它时最初返回每个页面(作为它自己的对象)。我的目标是编写一个将所有页面作为页面对象数组返回的包装器。有人可以解释为什么这不起作用吗?


我试过:


添加 .then 和返回条件 - 因为我希望 parseFileItems 方法返回一个值:


let pages = [];


new pdfreader.PdfReader()

  .parseFileItems(pp, function(err, item) {

    {

      if (!item) {

        return pages;

      } 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);

      }

    }

  })

  .then(() => {

    console.log("done" + pages.length);

  });

并得到了错误


TypeError:无法读取未定义的属性“then”


我正在修改的功能(来自包文档):


var pdfreader = require("pdfreader");


var rows = {}; // indexed by y-position


function printRows() {

  Object.keys(rows) // => array of y-positions (type: float)

    .sort((y1, y2) => parseFloat(y1) - parseFloat(y2)) // sort float positions

    .forEach(y => console.log((rows[y] || []).join("")));

}


new pdfreader.PdfReader().parseFileItems("CV_ErhanYasar.pdf", function(

  err,

  item

) {

  if (!item || item.page) {

    // end of file, or page

    printRows();

    console.log("PAGE:", item.page);

    rows = {}; // clear rows for next page

  } else if (item.text) {

    // accumulate text items into rows object, per line

    (rows[item.y] = rows[item.y] || []).push(item.text);

  }

});


回首忆惘然
浏览 103回答 2
2回答

凤凰求蛊

这里似乎同时存在几个问题/误解。让我们试着一次看一次。首先,您似乎认为外部函数将返回(“传递”)您的回调的返回值正如您在库源代码中看到的那样,情况并非如此。此外,它甚至没有意义,因为回调为每个项目调用一次。那么,对于 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)})注意:使用异步生成器你会得到更好的代码,但是现在在这里解释太多了,因为从回调到异步生成器的转换没有你想象的那么简单。

POPMUISE

如果要链接 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);    });
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript