Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/456.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 承诺解决后如何调用函数?_Javascript_Firebase_Google Cloud Functions_Firebase Cloud Messaging - Fatal编程技术网

Javascript 承诺解决后如何调用函数?

Javascript 承诺解决后如何调用函数?,javascript,firebase,google-cloud-functions,firebase-cloud-messaging,Javascript,Firebase,Google Cloud Functions,Firebase Cloud Messaging,下面的代码是针对我的FCM函数的,在构建要发送的有效负载之前,我正在侦听firestore获取令牌。每次发送时,系统都会记录令牌为空。发送fcm时,如何确保其不为空 let functions = require('firebase-functions'); let admin = require('firebase-admin'); admin.initializeApp(functions.config().firebase); exports.sendNotification =fu

下面的代码是针对我的FCM函数的,在构建要发送的有效负载之前,我正在侦听firestore获取令牌。每次发送时,系统都会记录令牌为空。发送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上以尽可能快的速度迭代,而不是等待查询在其中完成。这意味着代码将在
令牌
填充之前继续

相反,您应该收集循环中的每个承诺,并使用
Promise.all()
等待整个批处理,然后从中返回承诺以指示所有工作何时完成。这将确保
tokens
在执行链中的下一个
之前包含您想要的所有内容

代码的一般形式如下所示:

.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
})
另见: