我是新来使用云函数的Firebase与HTTP触发的功能,我很困惑如何正确终止功能。我不确定是否应该使用res.sendStatus、返回一个promise,或者两者都使用。
我的函数的目标是循环遍历集合“communities”中的几个文档。每个 community 都有一个文档集合,我在其中查询具有最高值'hotScore'的文档。然后,我将包含该文档的iOS推送通知发送到一个主题(该给定社区中的所有用户)。
不幸的是,当代码运行时,我得到了几个错误,例如Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
和Unhandled rejection
。我认为这是由于我在处理函数终止时的疏忽,尽管我对迄今为止所查看的在线资源感到困惑。有人介意看看我的代码/给我指出正确的方向吗?谢谢你!
exports.sendNotificationTrendingPost = functions.https.onRequest(async (req, res) => {
//Get communities collection from Firestore
return admin.firestore().collection('communities').get().then((communities) => {
var communityPromises = [];
//Loop through each community
communities.forEach((community) => {
let communityID = community.get('communityID');
let communityName = community.get('name');
//Get the post with the highest hotScore
let communityPromise = admin.firestore().collection('communities').doc(communityID).collection('posts').orderBy('hotScore', 'desc').limit(1).get().then((posts) => {
let hottestPost = posts[0];
let postID = hottestPost.get('postID');
let postText = hottestPost.get('text');
let currentDate = Date.now() / 1000;
var message;
//Verify that the hottest post was posted in the past 24 hours
if (hottestPost.get('date') > (currentDate - 86400)) {
//Build the notification text (shortening if too long)
let shortenedPostText = postText.substring(0,60);
var textEnd = '';
if (postText.length > 60) {
textEnd = '...';
}
let notificationText = 'Trending post on ' + communityName + ': ' + shortenedPostText + textEnd;
//Build the push notification
message = {
apns: {
headers: {
'apns-push-type': 'alert'
},
payload: {
aps: {
alert: {
body: notificationText,
},
},
postID: postID,
},
},
topic: communityID
}
}
//Send the message and return the promise
if (message === null) {
return null;
} else {
return admin.messaging().send(message);
}
})
.catch(error => {
console.log(error);
res.status(500).send(error);
})
if (communityPromise !== null) {
communityPromises.push(communityPromise);
}
})
res.sendStatus(200);
return Promise.all(communityPromises);
})
.catch(error => {
console.log(error);
res.status(500).send(error);
})
})
1条答案
按热度按时间nwlls2ji1#
正如samthecodingman建议的那样,在您的情况下使用
async/await
要好得多,因为它会简化代码,使其更容易阅读。下面的变化应该可以做到这一点(未经测试)。请注意我们如何使用一个社区名称数组来将名称从一个循环传递到另一个循环。这是可行的,因为对于
Promise.all()
,返回值是按照传递的Promises的顺序,而不管完成顺序如何。