如何在Javascript中将Promises与async和await一起使用

时间:2020-02-19 14:02:58

标签: javascript promise async-await

我有一个返回所有对象的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);
      })
}

并且对象具有要解析为名称的ID,因此 我编写了一个函数来解析其名称,并将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
                    });
                });
}
我希望在每个循环上调用该函数,并在执行时更新代码,如何 我会那样做吗?

2 个答案:

答案 0 :(得分:0)

只需将您的函数包装在Promise中,然后使用resolvereject返回值:

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

答案 1 :(得分:0)

它应该看起来像这样。

您的代码正在向每个入站请求发送多个异步请求。从性能的角度来看,这些应该并行发生:您不应简单地等待每个请求返回之后再发出下一个请求。这就是为什么我在解决方案中使用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
}