简体   繁体   中英

Why do I get "Expected catch() or return"-error when trying to connect to firestore via cloud-function?

I use google cloud firestore with a certain amount of collections. I am trying to write a google cloud function that returns the number of collections in this firestore upon http-request.

So I wrote the following index.js -file drawing from this question :

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

exports.queryForData = functions.https.onRequest((request, response) => {
    var db = admin.firestore();
    db.get().then(snap => {
        response.status(200).send({length: snap.size});
        })
    }); 

After deploying, I get this error:

在此处输入图片说明

The strange thing is: When I delete the line var db = admin.firestore(); I get the very same error. So I suspect, that I am not correctly connecting to firestore at all.

What am I doing wrong?

As explained on the official video on HTTP Cloud Function, you should add a catch() block to your Cloud Function, as follows:

exports.queryForData = functions.https.onRequest((request, response) => {
    var db = admin.firestore();
    db.get()
    .then(snap => {
       response.status(200).send({length: snap.size});
       //Or response.send({length: snap.size});
    })
    .catch(error => {
       console.log(error);
       response.status(500).send(error);
    })
}); 

But, in addition, if I am not mistaken, there is (another) error in your Cloud Function : you do db.get() but there is not get() method for the Firestore service interface . You should call the get() method on a CollectionReference , since you are using the size() method on the returned QuerySnapshot (ie snap ):

exports.queryForData = functions.https.onRequest((request, response) => {
    var db = admin.firestore();
    db.collection('collectionId').get()
    .then(snap => {
       response.status(200).send({length: snap.size});
       //Or response.send({length: snap.size});
    })
    .catch(error => {
       console.log(error);
       response.status(500).send(error);
    })
}); 

Note that you could also call get() on a DocumentReference .

You need to return a value after the Promise finishes, in your case you can do the following:

exports.queryForData = functions.https.onRequest((request, response) => {
var db = admin.firestore();
return db.get().then(snap => {
     response.status(200).send({length: snap.size});
    })
});

The call to Firestore is asynchronous and you must make sure that you are managing the lifecycle of your cloud function for that.

The documentation states the following

  • Resolve functions that perform asynchronous processing (also known as "background functions") by returning a JavaScript promise.
  • Terminate HTTP functions with res.redirect(), res.send(), or res.end().
  • Terminate a synchronous function with a return; statement.

You can fix this by simply adding a return statement to your db.get() . And also, to get rid of your lint error, you should return a value from inside your handler. You can either return null or just return the response.send()

By omitting a return statement, it will implicitly resolve to undefined ... which probably why you get the warning.

exports.queryForData = functions.https.onRequest((request, response) => {
    var db = admin.firestore();
    return db.get().then(snap => {
        response.status(200).send({length: snap.size});
        return null;
        })
    }); 

The returned promise from db.get() will ensure that the function stays alive until your HTTP response has been sent and also terminates the function after the promise is resolved.

By not finalizing your functions properly, they might run until they timeout. See this video: https://youtu.be/xu5A1seU6PU?t=233

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM