有没有一种方法可以不使用嵌套承诺来嵌套?

时间:2020-06-11 04:22:42

标签: javascript firebase promise google-cloud-functions

在下面的云函数中,我使用自动生成的ID和5个字段值填充collection-1。在添加每个文档时,我将使用文档名称作为属性之一填充另一个集合,该属性包含先前自动生成的文档名称作为字段,

Collection-1
    -auto-id
          -property1
          -property2
          -property3
Collection-2
    property2
          -auto-id from collection-1

维护Collection-2可以更快地查找数据。

exports.addSafe = functions.https.onCall((data, context) => {
    // The HTTP endpoint is going to receive an object with an attribute "data", which is going to contain an array of objects with every single safe data point to add

        for (let i=0; i<data.length; i++) {
                db.collection('Safes').add(data[i])
                .then((docRef) => {

                    db.collection('Safes-Hardware').doc(data[i]['Mac address Check']).set({
                        "ID" : docRef.id
                    })
                    .then((value) =>{
                        console.log("Reference added with ID: ", value.id);
                        return { message: "Successful" }
                    })
                    .catch(err => {
                        console.log('Oops!, error while adding lookup details',err);
                        return { message: "Error while adding lookup details",err }
                    })
                    console.log('Mac written with ID: ', docRef.id); 
                    return { message: "Success is within the palm of our hands." }
                })
                .catch(err => {
                    console.log('Error logged', err);
                })

        }
    }
})

更新代码-使用嵌套的异步等待

exports.addSafe = functions.https.onCall((data, context) => {
    // The HTTP endpoint is going to receive an object with an attribute "data", which is going to contain an array of objects with every single safe data point to add

    const attributesToDelete = ["CARTON#", "NO#"] // This first function call is implemented initially because of the first CSV file that I was given, which includes unnecessary columns, like "Carton" or "No". The factory producing the safes should send a CSV file with no unecessary extra data. If they do, this function should theoretically take care of removing those data points, to ensure that the database only holds the necessary data points ;)
    deleteAttributes(data, attributesToDelete);
    let validated = true;

    //validateForm(data);

    if (validated === false) {
        console.log('Data cannot be validated. Misses the correct attributes')
    } else {

        for (let i=0; i<data.length; i++) {
                try
                {

                    // eslint-disable-next-line no-await-in-loop
                    var ifPresent = db.collection("Safes-Hardware").doc(data[i]['Mac address Check']);
                    ifPresent.get()
                    .then(async (doc)=>{
                        if (!doc.exists) 
                        {
                            console.log("Document does not exit. Proceeding to add");
                            try{
                                // eslint-disable-next-line no-await-in-loop
                                const docRef = await db.collection('Safes').add(data[i])
                                console.log('Mac written with ID: ', docRef.id); 
                                try{
                                    // eslint-disable-next-line no-await-in-loop
                                    await db.collection('Safes-Hardware').doc(data[i]['Mac address Check'])
                                    .set({
                                            "ID" : docRef.id
                                        })
                                    console.log("Reference added");
                                }
                                catch(err){
                                    console.log("Error while adding reference",err)
                                } 
                            }
                            catch(err){
                                console.log("Error while adding data to 'Safe' collection")
                            }

                        }
                        else
                        {
                            console.log("Document exists in database. Skipping safe with MAC Address: ",data[i]['Mac address Check']);
                        }
                        return { message: "Success is within the palm of our hands." } 
                    })
                    .catch((error)=>{
                        console.log("Error while checking for duplicates", error);

                    });

                }
                catch(error){
                    console.log("Error logged",error)
                }
            }
        }
    })

有什么比使用嵌套承诺更好的方法呢? 当我不填充第二个集合时,代码可以完美地工作。但是,当第二个集合也被填充时,我偶尔会收到以下错误(3/10次)

错误:

 Error logged { Error: The referenced transaction has expired or is no longer valid.
    at Http2CallStream.call.on (/srv/node_modules/@grpc/grpc-js/build/src/client.js:96:45)
    at emitOne (events.js:121:20)
    at Http2CallStream.emit (events.js:211:7)
    at process.nextTick (/srv/node_modules/@grpc/grpc-js/build/src/call-stream.js:71:22)
    at _combinedTickCallback (internal/process/next_tick.js:132:7)
    at process._tickDomainCallback (internal/process/next_tick.js:219:9)
  code: 3,
  details: 'The referenced transaction has expired or is no longer valid.',
  metadata: Metadata { options: undefined, internalRepr: Map {} } } 

Collections - Safe

Safes-Hardware

1 个答案:

答案 0 :(得分:0)

请尝试首先使用Custom Document Name创建一个集合,然后按照以下步骤将数据设置到文档中:

 const doc = db.collection('Safes').doc(data[i]['Mac address Check'])
 doc.set({"ID" : docRef.id })