云HTTPS函数:返回Promisee中的Promise



我目前正在使用Firebase开发HTTPS云功能,包括删除我的Android用户请求的帖子。

总体思路

工作流程是(整个代码在本SO问题的末尾可用(:1(Firebase检查用户身份(admin.auth().verifyIdToken(;2( Firestore从必须删除的帖子中获取数据(deleteDbEntry.get().then()(;3( 云存储准备删除在获取的数据中找到的文件(.file(filePath).delete()(;4( Firestore准备一个批次来删除帖子(batch.delete(deleteDbEntry);(并使用获得的数据更新点赞/取消点赞(batch.update(updateUserLikes,(;5( 执行删除文件和批处理的承诺(return Promise.all([deleteFile, batch_commit])(。

预期行为

我想检查用户身份。如果成功,请使用Firebase获取请求的帖子以删除其数据。如果它成功了,我会希望在相同的承诺中执行Firestore批处理和云存储文件删除(这就是我使用Promise.all([deleteFile, batch_commit]).then()的原因(。如果身份检查失败,或者数据获取失败,或者批量失败,我想告诉Android应用程序。如果所有的成功,幂等。

由于所有这些操作都在云HTTPS函数中,所以我必须返回一个promise。我认为,如果这些操作成功,这个承诺将对应于所有操作,如果至少有一个操作不成功,则对应于一个错误(?(。

实际行为

目前,我只是返回Firebase用户身份检查的承诺。

我的问题&我的问题

我无法从实际行为转到预期行为,因为:

  1. 我觉得我不太清楚我是否应该在这个云HTTPS功能中返回对应于"所有这些操作都成功了,或者至少有一个不成功"的承诺

  2. 由于这些操作是嵌套的(除了批量中存在的Firestorage文件删除+Firestore后期删除(,我无法返回类似Promise.all()的内容。

我的问题

你能告诉我我说得对吗(第1点(,如果不对:我该怎么办?如果是:因为第2点,我该怎么做。?

Whole Firebase Cloud HTTPS功能代码

注意:我删除了我的输入数据控件,使我的代码更加清晰

exports.deletePost = functions.https.onCall((data, context) => {
return admin.auth().verifyIdToken(idToken)
.then(function(decodedToken) {
const uid = decodedToken.uid;
const type_of_post = data.type_of_post;
const the_post = data.the_post;
const deleteDbEntry = admin_firestore.collection('list_of_' + type_of_post).doc(the_post);
const promise = deleteDbEntry.get().then(function(doc) {
const filePath = type_of_post + '/' + uid + '/' + data.stored_image_name;
const deleteFile = storage.bucket('android-f.appspot.com').file(filePath).delete();
const batch = admin.firestore().batch();
batch.delete(deleteDbEntry);
if(doc.data().number_of_likes > 0) {
const updateUserLikes = admin_firestore.collection("users").doc(uid);
batch.update(updateUserLikes, "likes", FieldValue.increment(-doc.data().number_of_likes));
}
const batch_commit = batch.commit();
return Promise.all([deleteFile, batch_commit]).then(function() {
return 1;
}).catch(function(error) {
console.log(error);
throw new functions.https.HttpsError('unknown', 'Unable to delete the post. (2)');
});
}).catch(function(error) { 
console.log(error);
throw new functions.https.HttpsError('unknown', 'Unable to delete the post. (1)');
});
return promise;

}).catch(function(error) {
console.log(error);
throw new functions.https.HttpsError('unknown', 'An error occurred while verifying the token.');
});
});

您应该注意,您实际上是在定义一个可调用的云函数,而不是HTTPS函数,因为您定义了:

exports.deletePost = functions.https.onCall((data, context) => {..});

与HTTPS相比,可调用云函数的优势之一是它"自动反序列化请求主体并验证身份验证令牌"。

因此,您可以简单地使用context.auth.uid;获取用户uid


现在,关于"编排"不同调用的方式,IMHO您应该将异步Firebase方法(Firestore方法和Cloud Storage方法(返回的不同Promise链接起来,如下所示:

exports.deletePost = functions.https.onCall((data, context) => {
//....
const uid = context.auth.uid;
let number_of_likes;
const type_of_post = data.type_of_post;
const the_post = data.the_post;
const deleteDbEntry = admin_firestore.collection('list_of_' + type_of_post).doc(the_post);
return deleteDbEntry.get()
.then(doc => {
number_of_likes = doc.data().number_of_likes;
const filePath = type_of_post + '/' + uid + '/' + data.stored_image_name;
return storage.bucket('android-f.appspot.com').file(filePath).delete();
})
.then(() => {
const batch = admin.firestore().batch();
batch.delete(deleteDbEntry);
if (number_of_likes > 0) {
const updateUserLikes = admin_firestore.collection("users").doc(uid);
batch.update(updateUserLikes, "likes", FieldValue.increment(-doc.data().number_of_likes));
}
return batch.commit();
}).catch(function (error) {
console.log(error);
throw new functions.https.HttpsError('....', '.....');
});
});

在您的情况下,我不认为使用Promise.all()会带来任何兴趣,因为正如这里所解释的,"如果任何传入的promise被拒绝,Promise.all将异步拒绝被拒绝的promise的值,无论其他promise是否已解决"。

在撰写本文时,无法将所有这些对不同Firebase服务的异步调用分组为一个原子操作。

即使最后的批处理写入是原子的,也可能发生云存储中的文件被正确删除,但对Firestore的批处理写操作没有执行的情况,例如,因为Firestore服务存在问题。


另外,请注意,在Promise链的末尾只需要一个异常处理程序。如果您想区分异常的原因,通过向前端发送不同的错误消息,您可以使用本文中介绍的方法。

本文展示了如何定义不同的自定义Error类(从标准的内置Error对象派生(,这些类用于检查异常处理程序中的错误类型。

相关内容

  • 没有找到相关文章

最新更新