【问题标题】:Defining asynchrosnous function and using it in a forEach loop定义异步函数并在 forEach 循环中使用它
【发布时间】:2019-09-06 15:31:38
【问题描述】:

我正在尝试使用来自 firestore 数据库的数据将 tex 文件编译为 PFD。完成后,脚本不会终止。我发现可以使用 process.exit() 让它退出。但是,它会终止仍在压缩 tex 文件的子进程。所以,我需要一个异步函数。 我找到的关于如何制作它们的指南并没有特别帮助我。我对 javascript 还是很陌生,任何臃肿对我来说仍然非常混乱。

我找到的关于如何制作它们的指南并没有特别帮助我。我对javascript还是很陌生,任何臃肿对我来说仍然很困惑。 在下面提到的带有async 的makePDF 函数和带有await 的函数调用不起作用,据我了解,它已经过时了。 我尝试实现一个承诺,但不明白它们的语法是如何工作的。只需将 .then() 附加到 for 循环中的函数调用就足以使循环等待函数完成吗? 如何使这个特定的异步? 它是否已经在其主体中使用了异步函数? 我知道承诺用于将生产者生产的任何东西返还给消费者。现在,我的制片人不生产任何要退货的东西。这有关系吗?

我从 for 循环中调用的函数:

function makePDF(object){
    let input = fs.readFileSync('main.tex', 'utf8');
    const outNameTex = object.ID + '.tex';
    const outNamePDF = object.ID + '.pdf';

    makeTEX(object, input, outNameTex);

    const infile = fs.createReadStream(outNameTex);
    const outfile = fs.createWriteStream(outNamePDF);
    const pdf = latex(infile);

    pdf.pipe(outfile);
    pdf.on('error', err => console.error(err));
    pdf.on('finish', () => {console.log('PDF generated!')});
}

还有我的循环函数:

firebase.auth().onAuthStateChanged((user) => {
    if (user) {
      console.log('user');
      db.collection('objects').where('printed', '==', false).get().then((snapshot) => {
        snapshot.forEach((doc) => {
          console.table(doc.data());
          makePDF(doc.data());
          })
          process.exit();
        })
      .catch((err) => {
        console.log('Error getting documents', err);
      });
    } else {
      console.log('no user');
    }
});

它为每个文档输出一个表格,但没有PDF generated.

【问题讨论】:

    标签: javascript asynchronous promise


    【解决方案1】:

    async/await 与 for 循环一起使用可能会很棘手,这是因为 async 函数返回一个 Promise...如果您将 async/await 语法转换为本机 Promise 语法,您可能会找出问题所在。

    您想要做的是使用Array.map 将每个文档映射/转换为在makePDF 完成后解决的promise,然后使用Promise.all 等待所有promise 解决..

    解决方案应该是这样的

    function makePDF(object){
      return new Promise((resolve, reject) => {
        let input = fs.readFileSync('main.tex', 'utf8');
        const outNameTex = object.ID + '.tex';
        const outNamePDF = object.ID + '.pdf';
    
        makeTEX(object, input, outNameTex);
    
        const infile = fs.createReadStream(outNameTex);
        const outfile = fs.createWriteStream(outNamePDF);
        const pdf = latex(infile);
    
        pdf.pipe(outfile);
        pdf.on('error', reject);
        pdf.on('finish', () => {console.log('PDF generated!'); resolve();});
    }
    
    firebase.auth().onAuthStateChanged((user) => {
        if (user) {
          console.log('user');
          db.collection('objects').where('printed', '==', false).get().then((snapshot) => {
            const promiseArr = snapshot.docs.map((doc) => {
              console.table(doc.data());
              return makePDF(doc.data());
              })
              Promise.all(promiseArr)
                .then(() => {
                  process.exit();
                })
            })
          .catch((err) => {
            console.log('Error getting documents', err);
          });
        } else {
          console.log('no user');
        }
    });
    

    【讨论】:

    • snapshot.map 是做什么的?它对我产生了错误not a function
    • @Harri 我自己没有尝试过这段代码,但看起来 firebase 没有返回正常的 JavaScript 数组,请尝试使用 snapshot.docs.map 代替这里提到的stackoverflow.com/questions/46614055/…。 map 类似于 forEach 但它将数组转换为函数返回的任何内容,在这种情况下,Promise 返回一个新数组,请参阅developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    • 地图错误已解决,但 PDF 仍未编译完成,PDF generated 未打印。
    • 我仍然有一个狂野的resolve();。现在可以了。非常感谢!!
    猜你喜欢
    • 1970-01-01
    • 2020-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多