Firestore cloud function trying to use a batch to

2019-08-03 18:17发布

I am triggering this function in my cloud code. Before I added the returns and the batch lines, everything worked but it was getting errors for missing return promises and the writes were taking very long to write.

After following some of these videos here I tried correcting the return promises, but now the function is not working at all

I am coming from swift background and am not familiar with javascript much. I have tried the following code

exports.updateFeeds = functions.firestore
    .document('feedItems/{feedID}')
    .onUpdate((change, context) => {
    const newValue = change.after.data();
    const oldValue = change.before.data();
    const uid = newValue.uid;
    var userRef = db.collection("users").doc(uid);
    var authorRef = db.collection("users").doc(newValue.creatorUid);
    var postRef = db.collection("posts").doc(newValue.postId);
    var resharedRef = db.collection("resharedPostPopularities").doc(newValue.postId);
    var feedRef = db.collection("feedItems");
    let followers = [];
    if (newValue.wasViewed && !oldValue.wasViewed) {
        authorRef.get().then((doc) => {
            let data = doc.data();
            let postview_count = data.postViewCount;
            return authorRef.update({
                postViewCount: Number(postview_count) + 1
            }).then(() => {
                return userRef.collection('viewedPosts').doc('content').update({
                    postIds: admin.firestore.FieldValue.arrayUnion(newValue.postId)
                }).then(() => {
                    postRef.get().then((doca) => {
                        let datap = doca.data();
                        let postresh_count = Number(datap.reshareCount);
                        let postview_count = Number(datap.viewCount) + 1;
                        if (newValue.wasReshared) {
                            postresh_count = postresh_count + 1;
                        }
                        let popu = (postresh_count / postview_count) || 0;
                        if (postview_count * postresh_count == 0) {
                            popu = 0;
                        }
                        return postRef.update({
                            viewCount: postview_count,
                            popularity: popu,
                            reshareCount: postresh_count
                        }).then(() => {
                            postRef.collection('views').doc('content').get().then((docr) => {
                                if (typeof docr.data() == 'undefined') {
                                    return postRef.collection('views').doc('content').set({
                                        uids: admin.firestore.FieldValue.arrayUnion(uid)
                                    });
                                }
                                else {
                                    return postRef.collection('views').doc('content').update({
                                        uids: admin.firestore.FieldValue.arrayUnion(uid)
                                    });
                                }
                            });
                            if (newValue.wasReshared) {
                                postRef.collection('reshares').doc('content').get().then((elon) => {
                                    console.log('elon is');
                                    console.log(elon.data());
                                    if (typeof elon.data() == "undefined") {
                                        return postRef.collection('reshares').doc('content').set({
                                            uids: [uid]
                                        });
                                    }
                                    else {
                                        return postRef.collection('reshares').doc('content').update({
                                            uids: admin.firestore.FieldValue.arrayUnion(uid)
                                        });
                                    }
                                });
                                userRef.collection('followers').doc('content').get().then((doc) => {
                                    let data = doc.data();
                                    if (typeof data.uids != 'undefined') {
                                        followers = data.uids;
                                        console.log('followers is:');
                                        console.log(followers);
                                    }
                                }).then(() => {
                                    let rep = 0;
                                    let validis = [];
                                    let batch = db.batch();
                                    followers.forEach((fol) => {
                                        rep++;
                                        if (fol != newValue.creatorUid && fol != uid) {
                                            feedRef.where('postId', '==', newValue.postId).where('uid', '==', fol).get().then((snapshot) => {
                                                if (snapshot.empty) {
                                                    validis.push(fol);
                                                    console.log('No feed with post ' + newValue.postId + ' and user ' + fol);
                            // here we want to add the batch for this write
                                                    batch.set(feedRef, {
                                                        createdAt: admin.firestore.FieldValue.serverTimestamp(),
                                                        uid: fol,
                                                        creatorUid: newValue.creatorUid,
                                                        postId: newValue.postId,
                                                        isResharedPost: true,
                                                        wasViewed: false,
                                                        wasReshared: false,
                                                        wasLiked: false,
                                                        wasDirectlyShared: false
                                                    })
                                                    batch.commit().then((res) => {
                                                        console.log(rep + ' out of ' + followers.length);
                                                        if (rep == followers.length) {
                                                            console.log('finally its ' + followers.length);
                                                            console.log('resharereffffingngg');
                                                            resharedRef.get().then((docr) => {
                                                                if (typeof docr.data() == 'undefined') {
                                                                    console.log('docr  unexists');
                                                                    return resharedRef.set({
                                                                        popularity: popu,
                                                                        uids: validis
                                                                    });
                                                                }
                                                                else {
                                                                    console.log('docr exists');
                                                                    let datar = docr.data();
                                                                    let datar_uids = datar.uids;
                                                                    let c = datar_uids.concat(validis.filter(function (item) {
                                                                        return datar_uids.indexOf(item) < 0;
                                                                    }));
                                                                    return resharedRef.update({
                                                                        popularity: popu,
                                                                        uids: c
                                                                    });
                                                                }
                                                            });
                                                        }
                                                    });
                                                }
                                            });
                                        }
                                    });
                                });
                            }
                            resharedRef.get().then((docr) => {
                                console.log(docr.data());
                                console.log(typeof docr.data());
                                if (typeof docr.data() != 'undefined') {
                                    return resharedRef.update({
                                        uids: admin.firestore.FieldValue.arrayRemove(newValue.uid)
                                    });
                                }
                            });
                        });
                    });
                });
            });
        });
    }
});

1条回答
老娘就宠你
2楼-- · 2019-08-03 18:50

Okay i see your problem here and correct me if I'm wrong, your current format is like this:

exports.updateFeeds = functions.firestore
.document('feedItems/{feedID}')
.onUpdate((change, context) => { 


return somePromise.get().then(returnData=>{
    dosomethingwith(returnData);
    return anotherpromise.get().then(anotherreturndata=>{
        dosomethingwith(anotherreturndata);
        })
    })
});

This style of promise writing will fail because you shouldn't nest your promises like that.

It should look something like this:

exports.updateFeeds = functions.firestore
.document('feedItems/{feedID}')
.onUpdate((change, context) => { 


return somePromise.get()//initial return function its return value is passed to returnData

    .then(returnData=>{//now we have the value that was returned from the function above

        return dosomethingwith(returnData);//do something with the data from somePromise.get()

    }).then(somethingWasDoneWithReturnData=>{ //this is the result of the dosomethingwith function because we returned it

        return anotherPromiseFunction.get();// now we need to return another promise

    }).then(returnFromAnotherPromiseFunction=>{//the result from anotherPromiseFunction gets passed into the block below this           doSomeThingWith(returnFromAnotherPromiseFunction);
        doSomeThingWith(returnFromAnotherPromiseFunction);
    })
});

Here is some of my code from one of my firebase functions that reverse geocodes addresses.

  return orderRef.get().then(doc=>{
    let order = doc.data();
    return order;
  }).then(order=> getAddresses(order.rectangles))
  .then(allAddresses=> eliminateDuplicates(allAddresses))
  .then(duplicateAddressesRemoved=> batchReverseGeocode(duplicateAddressesRemoved))
  .then(reverseGeocodedAddresses=> {
    allAddresses = reverseGeocodedAddresses;
    newAddressCount = allAddresses.length;
    newChargeTotal = calculatePrice(newAddressCount);
    console.log(allAddresses);
    console.log(newAddressCount);
    return writeFirebase(addressStorageRef, {addresses: reverseGeocodedAddresses}, null)
  })
  .then(noneObject=> updateFirebase(chargeRef, {status: "Charge Completed", finalChargeAmount: newChargeTotal, finalAddressCount: newAddressCount}, null))
  .then(noneObject=> updateFirebase(orderRef, {status: "Paid In Full", finalChargeAmount: newChargeTotal, finalAddressCount: newAddressCount}, null))
  .then(noneObject=>{
    //now we need to update the charge and move on
    return stripe.charges.capture(stripeChargeID, {amount: newChargeTotal})



  });
查看更多
登录 后发表回答