【问题标题】:How to use await inside await in async method and return result in last?如何在异步方法中的await内部使用await并最后返回结果?
【发布时间】:2020-05-03 07:37:24
【问题描述】:

我在await里面使用await,首先我在'a'行中使用了await,它工作正常,进入里面继续从'b'行到'd'行执行,但之后它需要进入那个查询并且必须从'e'行执行到'f'行,然后它必须最终执行'g'和'h'行并返回结果但问题是'd'行之后它不会在代码内部执行而是它来到'g'行并执行进一步的代码,然后返回到'e'行,这会导致错误。请帮帮我。


    var writeStreamData = '';
    var surveyBlockId = req.body.surveyBlockId;
    var title = req.body.title;
a.    await SurveyAnswer.find({'blockId': surveyBlockId}, (err, doc) => {
b.        if(doc.length!=0){
            userName = '';
            userIdList = Object.values(doc.reduce((acc,cur)=>Object.assign(acc,{[cur.userId.toString()]:cur}),{}));
            const pdfDoc = new PDFDocument({margin: 50});

            writeStreamData = pdfDoc.pipe(fs.createWriteStream('pdf_files/SurveyAnsweredUserList.pdf'));

            pdfDoc.fontSize(25).text('Home Owners Association', {align: "center"});
            pdfDoc.lineCap('butt').moveTo(30,80).lineTo(600,80).stroke();
            pdfDoc.moveDown();
            pdfDoc.fontSize(20).text('Survey Title : '+title);
            pdfDoc.moveDown();
            pdfDoc.fontSize(20).text('List of Users');
            if(doc.userIdList!=0){
                var counter = 0;
c.                userIdList.forEach(async element => {
                    userId = element.userId.toString();
d.                    await User.findOne({'_id':userId},async(err1, doc1) => {
e.                        if(!err1){
                            counter++;
                            userName = doc1.firstname + " "+ doc1.lastname;
                            pdfDoc.fontSize(15).text((counter)+". "+userName).moveDown();
                        }else{
                            counter++;
                            //return eachCb(err1)
                        }
                        //eachCb();
                    })
                }, function(err, data) {
                    if(err){
                        response = {
                            "message": "failed"
                        }
                        res.send(response);
                    }
                });
            }else{
                pdfDoc.fontSize(15).text('No User answered');
            }
f.            pdfDoc.end();
        }else{
            response = {
                "message": "failed"
            }
            res.send(response);
        }
    });

g.    fs.readFile(writeStreamData.path, function(err, data) {
h.        if(err) throw err;
        const pdf = data.toString('base64');
        response = {
            "message": "success",
            "data": pdf
        }
        res.send(response);
    })   
});```

【问题讨论】:

    标签: javascript node.js mongodb foreach async-await


    【解决方案1】:

    你做错了一些事情。你只能await一个承诺。 SurveyAnswer.find() 接收回调函数,它不返回承诺。所以,你不能等待它。 dg 也是如此。由于您使用的是回调样式,所以 await 在 a、d 和 g 前面是无用的。

    另外,awaitforEach 函数中也不起作用。请改用for...of

    【讨论】:

    • router.post('/downloadSurveyListPdf', async(req, res) => { var writeStreamData = ''; await SurveyBlock.find((err, doc) => { const pdfDoc = new PDFDocument ({margin: 50}); }); fs.readFile(writeStreamData.path, function(err, data) { res.send(response); }) });这是我的另一个代码,我在SurveyBlock.find()之前使用了await,然后只执行了'g'行,但是如果我删除await行'g'将首先执行,那么它会进入SurveyBlock.find(),这会导致错误跨度>
    【解决方案2】:

    在我看来,最简洁的方法是为 fs.readFile 之类的函数编写包装器,这些函数返回一个承诺而不是使用回调。这样可以更轻松地使用 await 组合所有内容。

    您可以使用bluebird 自动执行此转换,如以下答案所示:https://stackoverflow.com/a/34642827/303637

    【讨论】:

    • NodeJS util 库有 promisify() 函数将回调转换为承诺。
    【解决方案3】:

    您可以在 Promise 中使用 Promise 而不是 async await 来完成您的工作。 我有一个与您类似的示例,用于从 s3 存储桶中获取数据。你可以参考在promise里面实现promise。

     new Promise((lresolve) => {
            s3.listObjectsV2(params, (err, devicedata) => {
                if (!err) {
                    const data = devicedata.CommonPrefixes;
                    data.forEach(value => {
                        const prefix = value.Prefix.replace(params.Prefix, '').replace('/', '');
                        devices.push(prefix);
                    });
                    lresolve(devices);
                }
            });
        }).then(qDevices => {
            const devicePromise = [];
            qDevices.forEach(devicepath => {
                devicePromise.push(
                    new Promise((qresolve) => {
                        params.Prefix = `${staticPrefix + devicepath}/tyre/`;
                        let processedData = [];
                        s3.listObjectsV2(params, (err, data) => {
                            if (!err) {
                                const contents = data.Contents;
                                const fetch = [];
                                contents.forEach(content => {
                                    fetch.push(getObject(content))
                                });
                                Promise.all(fetch).then(data => {
                                    data.forEach(d => {
                                        processedData = processedData.concat(d);
                                    });
                                    qresolve(processedData);
                                });
                            }
                        });
                    }));
            });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-11
      • 2019-07-22
      • 1970-01-01
      • 2019-01-17
      • 2023-03-25
      • 1970-01-01
      • 2016-12-12
      • 1970-01-01
      相关资源
      最近更新 更多