javascript - 如何在正确的范围内做出 Promise,以便它具有要查询的正确值并返回?

标签 javascript node.js firebase firebase-cloud-messaging google-cloud-functions

当有人喜欢某张照片时,我尝试使用 Firebase Cloud Functions 发送通知。我已经处理了 Firebase 示例,展示了当有人关注您并尝试修改它时如何发送该示例。

问题是,我需要在函数中执行另一个附加查询,以获取喜欢照片的人的 key ,然后才能从用户 Node 获取他们的 token 。问题是 getDeviceTokensPromise 不知何故未实现,并且 tokensSnapshot.hasChildren 无法读取,因为它未定义。我该如何修复它?

    exports.sendPhotoLikeNotification = functions.database.ref(`/photo_like_clusters/{photoID}/{likedUserID}`)
        .onWrite((change, context) => {
          const photoID = context.params.photoID;
          const likedUserID = context.params.likedUserID;
          // If un-follow we exit the function
          if (!change.after.val()) {
            return console.log('User ', likedUserID, 'un-liked photo', photoID);
          }

          var tripName;
          var username = change.after.val()

          // The snapshot to the user's tokens.
          let tokensSnapshot;

          // The array containing all the user's tokens.
          let tokens;

          const photoInfoPromise = admin.database().ref(`/photos/${photoID}`).once('value')
            .then(dataSnapshot => {
              tripName = dataSnapshot.val().tripName;
              key = dataSnapshot.val().ownerKey;
              console.log("the key is", key)
              return getDeviceTokensPromise = admin.database()
              .ref(`/users/${key}/notificationTokens`).once('value');
    ///// I need to make sure that this returns the promise used in Promise.all()/////
            });


          return Promise.all([getDeviceTokensPromise, photoInfoPromise]).then(results => {
            console.log(results)
            tokensSnapshot = results[0];

            // Check if there are any device tokens.

//////This is where I get the error that tokensSnapshot is undefined///////
            if (!tokensSnapshot.hasChildren()) {
              return console.log('There are no notification tokens to send to.');
            }

            // Notification details.

            const payload = {
              notification: {
                title: 'Someone liked a photo!',
                body: `${username} liked one of your photos in ${tripName}.`,
              }
            };

        // Listing all tokens as an array.
        tokens = Object.keys(tokensSnapshot.val());
        // Send notifications to all tokens.
        return admin.messaging().sendToDevice(tokens, payload);
      });

最佳答案

好的,根据您的评论,这是更新的答案。

您需要链接您的 Promise,并且不需要使用 Promise.all() - 该函数用于异步任务的集合,所有这些任务都需要在您采取下一个操作之前完成(并行)。

您的解决方案应如下所示:

admin.database().ref(`/photos/${photoID}`).once('value')
    .then(dataSnapshot => {
        // Extract your data here
        const key = dataSnapshot.val().ownerKey;

        // Do your other stuff here
        // Now perform your next query
        return admin.database().ref(`/users/${key}/notificationTokens`).once('value');
    })

    .then(tokenSnapshot => {
        // Here you can use token Snapshot
    })

    .catch(error => {
        console.log(error);
    });

由于您的第二个网络请求取决于第一个网络请求的完成,因此请通过在第一个网络请求之后附加第二个 .then() 来链接您的 promise ,并且不要用分号 ; 终止它。如果在第一个 .then() 范围内创建的新 Promise 解析,它将调用第二个 .then() 函数。

如果您需要在第二个作用域中访问第一个 .then() 作用域中的变量,则必须在通用函数中声明它们,并在闭包作用域中分配它们。

您可以查看 promise chaining here 的更多信息。

关于javascript - 如何在正确的范围内做出 Promise,以便它具有要查询的正确值并返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50776237/

相关文章:

javascript - 单击后禁用单选按钮

javascript - jquery autocomplete - 下拉结果的条件样式

javascript - 如何安装react-bootstrap v0.32.4?

javascript - 如何在 NodeJS 中传递命令行参数?

javascript - 使用 Firebase Cloud Functions 批量写入

javascript - page.open() 函数对于某些 URL 无法正常工作

swift - 将 firebase pod 更新到最新版本时收到 "framework not found MeasurementNanoPB"错误

php - 当 MySQL 什么都不返回时 $result 会是什么?

firebase - "The plugin cloud_firestore could not be built due to the issue above."如何解决

firebase - 如何在 ListView 抖动中获得用户之间的距离?