承诺解决后如何调用函数?
How to call a function after the promise has been resolved?
以下代码适用于我的 FCM 函数,在构建要发送的有效负载之前,我正在听 firstore 获取令牌。每次发送时,系统都会记录令牌为空。发送fcm时如何确保它不为空?
let functions = require('firebase-functions');
let admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification =functions.firestore.document('chatrooms/{chatRoomId}/messages/{messageId}')
.onWrite((snap, context) => {
let message = snap.after.data().messageBody;
let messageSender = snap.after.data().senderName;
let messageUserId = snap.after.data().userId;
let chatRoomId = context.params.chatRoomId;
let tokens = [];
let chatRoomRef = admin.firestore().collection("chatrooms").doc(chatRoomId);
return admin.firestore().runTransaction(t => {
return t.get(chatRoomRef)
.then(chatroom => {
let usersArray = chatroom.data().chatMembers;
usersArray.forEach(user_id => {
let userIdRef = admin.firestore().collection("tokens").doc(user_id);
return t.get(userIdRef).then(doc => {
if (doc.exists) {
let user_token = doc.data().token;
functions.logger.log('token: ', token);
tokens.push(user_token);
}
}).catch(err => {
functions.logger.error(err);
})
});
});
}).then(() => {
//The transaction has run successfully, we expect tokens array to not be empty
functions.logger.log("Construction the notification message.");
const payload = {
data: {
data_type: "data_type_chat_message",
title: "Tuchat",
message: message,
sender_id: messageUserId,
sender_name: messageSender,
chatRoom_id: chatRoomId
}
};
const options = {
priority: "high",
timeToLive: 60 * 60 * 24
};
return admin.messaging().sendToDevice(tokens, payload).catch(err => {
functions.logger.error(err);
});
}).catch(err => {
functions.logger.error('Transaction error: ', err);
})
});
同样在尝试交易之前它返回空令牌。
问题在于您在 forEach 循环中处理承诺的方式。循环不会等待其内部代码解析承诺。目前它只是尽可能快地遍历每个用户 ID,而不是等待查询在其中完成。这意味着代码将在 tokens
可以填充之前继续。
您应该改为收集循环内的每个承诺,并使用 Promise.all()
等待整个批处理,然后 return 来自其中的承诺指示所有工作何时完成。这将确保 tokens
在执行链中的下一个 then
之前包含您想要的所有内容。
代码的一般形式是这样的:
.then(() => {
const promises = []
collection.forEach(item => {
const promise = doSomeWork()
promises.push(promise)
})
return Promise.all(promises)
})
.then(() => {
// this will continue only after all promises are resolved
})
另请参阅:
以下代码适用于我的 FCM 函数,在构建要发送的有效负载之前,我正在听 firstore 获取令牌。每次发送时,系统都会记录令牌为空。发送fcm时如何确保它不为空?
let functions = require('firebase-functions');
let admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification =functions.firestore.document('chatrooms/{chatRoomId}/messages/{messageId}')
.onWrite((snap, context) => {
let message = snap.after.data().messageBody;
let messageSender = snap.after.data().senderName;
let messageUserId = snap.after.data().userId;
let chatRoomId = context.params.chatRoomId;
let tokens = [];
let chatRoomRef = admin.firestore().collection("chatrooms").doc(chatRoomId);
return admin.firestore().runTransaction(t => {
return t.get(chatRoomRef)
.then(chatroom => {
let usersArray = chatroom.data().chatMembers;
usersArray.forEach(user_id => {
let userIdRef = admin.firestore().collection("tokens").doc(user_id);
return t.get(userIdRef).then(doc => {
if (doc.exists) {
let user_token = doc.data().token;
functions.logger.log('token: ', token);
tokens.push(user_token);
}
}).catch(err => {
functions.logger.error(err);
})
});
});
}).then(() => {
//The transaction has run successfully, we expect tokens array to not be empty
functions.logger.log("Construction the notification message.");
const payload = {
data: {
data_type: "data_type_chat_message",
title: "Tuchat",
message: message,
sender_id: messageUserId,
sender_name: messageSender,
chatRoom_id: chatRoomId
}
};
const options = {
priority: "high",
timeToLive: 60 * 60 * 24
};
return admin.messaging().sendToDevice(tokens, payload).catch(err => {
functions.logger.error(err);
});
}).catch(err => {
functions.logger.error('Transaction error: ', err);
})
});
同样在尝试交易之前它返回空令牌。
问题在于您在 forEach 循环中处理承诺的方式。循环不会等待其内部代码解析承诺。目前它只是尽可能快地遍历每个用户 ID,而不是等待查询在其中完成。这意味着代码将在 tokens
可以填充之前继续。
您应该改为收集循环内的每个承诺,并使用 Promise.all()
等待整个批处理,然后 return 来自其中的承诺指示所有工作何时完成。这将确保 tokens
在执行链中的下一个 then
之前包含您想要的所有内容。
代码的一般形式是这样的:
.then(() => {
const promises = []
collection.forEach(item => {
const promise = doSomeWork()
promises.push(promise)
})
return Promise.all(promises)
})
.then(() => {
// this will continue only after all promises are resolved
})
另请参阅: