Как использовать Promises с asyn c и ожидать в Javascript - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть метод, который возвращает JSON всех объектов

const getAllItems=async function(req,res){
    localDB.find({
        selector:{type:'item'},
        fields: ['_id', 'itemNumber','itemName',"compatablities","companyID"],
        sort: ['_id']
    }).then(async function (result) {
        if (result) {
            var refinedResult=[]
            //console.log(result.docs[0]);
            for (i = 0; i < result.docs.length; i++) {
                    var parentItem={
                        itemName:result.docs[i].itemName,
                        itemNumber:result.docs[i].itemNumber,
                        companyID:result.docs[i].companyID,
                        parentItemNo:"Parent"
                        }
                        console.log("before");

                        const resolvedN=await resolveName(parentItem.companyID);
                        console.log(resolvedN)
                        console.log("Passed");
                        refinedResult.push(parentItem);
                    for (j = 0; j < result.docs[i].compatablities.length || 0; j++) {
                        var oneCompatItemConstruct={
                            itemName:result.docs[i].itemName,
                            itemNumber:result.docs[i].compatablities[j].itemNumber,
                            companyID:result.docs[i].compatablities[j].companyID,
                            parentItemNo:result.docs[i].itemNumber,
                        }
                        //console.log(oneCompatItemConstruct);
                        refinedResult.push(oneCompatItemConstruct);
                }
              }
            return res.status(200).json({
                refinedResult
            })
        }
      }).catch(function (err) {
        console.log(err);
      })
}

, и объекты имеют идентификатор, который должен быть разрешен к имени, поэтому я написал функцию для разрешения его имени и принял cid как параметр и возвращает строку

function resolveName(c_id){
    localDB.find({
        selector:{type:'company',_id:c_id},
        fields: ['companyName'],
        })
        .then(company=>{
        if (company.docs.length >=1) {
            console.log(c_id);
            const result = company.docs[0].companyName
            return result
        }
        else{
            return null
        }}).catch(err => {
                    console.log(err);
                    res.status(500).json({
                        error: err
                    });
                });
}

я хочу, чтобы функция вызывалась для каждого l oop и обновляла код во время его выполнения, как бы я это сделал?

Ответы [ 2 ]

0 голосов
/ 19 февраля 2020

Вероятно, это должно выглядеть примерно так.

Ваш код отправляет несколько асинхронных запросов на один входящий запрос. С точки зрения производительности, это должно происходить параллельно: вам не следует просто ждать возврата каждого запроса, прежде чем делать следующий запрос. Вот почему я использую Promise.all в своем решении.

Обратите внимание, что я вижу по крайней мере одну логическую проблему с вашим кодом, которую я не могу исправить.

const getAllItemsQuery = {
    selector: { type: 'item' },
    fields: ['_id', 'itemNumber', 'itemName', "compatablities", "companyID"],
    sort: ['_id']
}

const getAllItems = async function(req, res) {
    const { docs } = await localDB.find(getAllItemsQuery)
    if (!docs) return
    const promises = docs.map((doc) => createRefinedResultForDoc(doc))
    return res.status(200).json({ refinedResult: (await Promise.all(promises)).flat() })
}

async function createRefinedResultForDoc({ itemName, itemNumber, companyID, compatibilities }) {
     const result =  [ { itemName, itemNumber, companyID, parentItemNo: "Parent" } ]         
     const resolvedN = await resolveName(companyID)
     // use resolvedN...
     compatibilities.forEach((compatibility) => {
         result.push({
             itemName,
             itemNumber: compatibility.itemNumber,
             companyID: compatibility.companyID,
             parentItemNo: itemNumber,
         }))
     return result
}

const createResolveNameQuery = (_id) => ({
    selector: { type: 'company', _id },
    fields: ['companyName'],
})

const resolveName = async(c_id) => {
    const { docs: [ doc ] } = await localDB.find(createResolveNameQuery(c_id))
    if (!doc) throw 'name not resolved'
    console.log(c_id)
    return doc.companyName
}
0 голосов
/ 19 февраля 2020

Просто оберните вашу функцию в Promise и верните значения с resolve и reject:

function resolveName(c_id) {
    return new Promise((resolve, reject) => {
        localDB.find({
                selector: { type:'company', _id:c_id },
                fields: ['companyName'],
            })
            .then(company=> {
                if (company.docs.length >= 1) {
                    console.log(c_id);
                    const result = company.docs[0].companyName
                    resolve(result)
                }
                else {
                    resolve(null)
                }
            })
            .catch(err => {
                reject(err);
                res.status(500).json({
                error: err
            });
        });
    });
}
...