Как использовать await внутри await в методе asyn c и возвращать результат последним? - PullRequest
0 голосов
/ 16 января 2020

использую await внутри await, сначала я использовал await в строке 'a', он работает нормально и входит внутрь, продолжает выполняться со строки 'b' до строки 'd', но после этого ему нужно go внутри этот запрос и должен выполняться из строки '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);
    })   
});```

Ответы [ 3 ]

1 голос
/ 16 января 2020

Вы делаете несколько вещей неправильно. Вы можете только await обещание. SurveyAnswer.find() получает функцию обратного вызова, она не возвращает обещание. Таким образом, вы не можете ждать этого. То же самое касается d и g . Поскольку вы используете стиль обратного вызова, await перед a, d и g бесполезен.

Кроме того, await не работает в функции forEach. Вместо этого используйте for...of.

0 голосов
/ 16 января 2020

Вы можете использовать Promise внутри Promise вместо asyn c, ожидая своей работы. У меня есть пример, похожий на ваш, который я использую для извлечения данных из корзины s3. Вы можете воспользоваться ссылкой, чтобы выполнить обещание внутри обещания.

 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);
                            });
                        }
                    });
                }));
        });
0 голосов
/ 16 января 2020

На мой взгляд, самый простой способ - написать оболочки для таких функций, как fs.readFile, которые возвращают обещание вместо использования обратного вызова. Это упрощает компоновку всего с await.

. Вы можете использовать bluebird для автоматизации этого преобразования, как показано в этом ответе: { ссылка }

...