简体   繁体   English

如何在 async 方法中使用 await 在 await 中并在最后返回结果?

[英]How to use await inside await in async method and return result in last?

am using await inside await, first i have used await in line 'a', it works fine and enters inside continues to execute from line 'b' to line 'd', but after that it needs to go inside that query and has to execute from line 'e' to line 'f', then it has to execute line 'g' and 'h' finally and return result but problem is after line 'd' it will not execute inside code instead it comes to line 'g' and executes further code and then comes back to line 'e' which causes error.我在等待中使用等待,首先我在“a”行中使用了等待,它工作正常并进入内部继续从“b”行到“d”行执行,但之后它需要进入该查询并且必须从“e”行执行到“f”行,然后它必须最终执行“g”行和“h”行并返回结果,但问题是在“d”行之后它不会在代码内部执行,而是到“g”行' 并执行进一步的代码,然后返回到导致错误的行 'e'。 Please help me out.请帮帮我。


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

You are doing a few things wrong.你做错了几件事。 You can only await a promise.你只能await一个承诺。 SurveyAnswer.find() receives a callback function, it doesn't return a promise. SurveyAnswer.find()接收回调函数,它不返回承诺。 So, you can't await it.所以,你不能等待。 Same goes for d and g . dg 也是如此 As you are using callback style so await in front of a, d and g is useless.由于您使用的是回调样式,因此在 a、d 和 g 前面await是无用的。

Also, await does not work in forEach function.此外, awaitforEach函数中不起作用。 Use for...of instead.使用for...of代替。

In my opinion the cleanest way is to write wrappers for functions like fs.readFile that return a promise instead of using a callback.在我看来,最fs.readFile方法是为fs.readFile函数编写包装器,这些函数返回承诺而不是使用回调。 This makes it easier to compose everything with await .这使得使用await组合所有内容变得更加容易。

You can use bluebird to automate this conversion as shown in this answer: https://stackoverflow.com/a/34642827/303637您可以使用bluebird自动执行此转换,如本答案所示: https : //stackoverflow.com/a/34642827/303637

You can make use of Promise inside Promise instead of async await to get your work done.您可以在 Promise 内部使用 Promise 而不是 async await 来完成您的工作。 I have an example similar to yours which i am using to fetch data from s3 bucket.我有一个类似于您的示例,我正在使用它从 s3 存储桶中获取数据。 You can take reference to implement promise inside promise.你可以参考在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);
                            });
                        }
                    });
                }));
        });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM