- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在使用 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) 执行删除文件和批处理的 promise ( return Promise.all([deleteFile, batch_commit])
)。
我想检查用户身份。如果成功,则使用 Firebase 获取请求的帖子以删除数据。如果成功,我希望在同一个 promise 中执行 Firestore 批处理和云存储文件删除(这就是我使用 Promise.all([deleteFile, batch_commit]).then()
的原因)。如果身份检查失败,或者数据获取失败,或者批处理失败,我想告诉Android应用程序。如果一切成功,同上。
由于所有这些操作都在 Cloud HTTPS Function 中,因此我必须返回一个 promise 。我认为,这个 promise 将对应于所有这些操作(如果它们成功),或者如果至少有一个操作不成功(?),则对应于错误(?)。
目前,我只是返回 Firebase 用户身份检查的 promise 。
我无法从实际行为转向预期行为,因为:
我觉得自己不太清楚是否应该在这个 Cloud HTTPS Function 中返回“所有这些操作都成功,或者至少有一个不成功”对应的 Promise
由于这些操作是嵌套的(批量中存在的 Firestorage 文件删除 + Firestore 后删除除外),我无法返回类似 Promise.all()
的内容.
您能告诉我我是否正确(第 1 点),如果不正确:我该怎么办?如果是:由于第 2 点,我该怎么做?
注意:我已经删除了输入数据控件以使我的代码更易于理解。
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.');
});
});
最佳答案
您应该注意,您实际上正在定义 Callable Cloud Function而不是 HTTPS one ,既然你这样做了:
exports.deletePost = functions.https.onCall((data, context) => {..});
可调用云函数相对于 HTTPS 的优势之一是它“自动反序列化请求正文并验证身份验证 token ”。
因此,您可以简单地使用 context.auth.uid;
获取用户 uid
。
现在,关于“编排”不同调用的方式,恕我直言,您应该链接异步 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()
不会带来任何兴趣,因为,正如所解释的 here ,“如果任何传入的 Promise 被拒绝,Promise.all
会以被拒绝的 Promise 的值异步拒绝,无论其他 Promise 是否已解决”。
在撰写本文时,无法将对不同 Firebase 服务的所有异步调用分组到一个原子操作中。
即使最后的批量写入是原子的,也可能会发生 Cloud Storage 中的文件被正确删除但对 Firestore 的批量写入未执行的情况,例如因为 Firestore 服务出现问题。
<小时/>另外,请注意,您只需要 Promise 链末尾的一个异常处理程序。如果您想区分异常的原因,通过向前端发送不同的错误消息的方式,您可以使用此 article 中介绍的方法。 .
本文展示了如何定义不同的自定义错误类(派生自标准内置错误对象),这些类用于检查异常处理程序中的错误类型。
关于javascript - 云HTTPS函数: returning a Promise which is inside a Promisee,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60587876/
我目前正在使用 Firebase 开发 HTTPS 云功能,包括删除我的 Android 用户请求的帖子。 总体思路 工作流程是(整个代码在此SO问题的末尾可用):1)Firebase检查用户身份(
我是一名优秀的程序员,十分优秀!