【问题标题】:Error "Function returned undefined, expected Promise or value" even after return in all places错误“函数返回未定义,预期的承诺或值”即使在所有地方都返回
【发布时间】:2019-09-07 05:21:45
【问题描述】:

我是 Node.js 的新手,即使在阅读了其他 stackflow 用户提供的教程之后,我仍然在为 Promises 苦苦挣扎。我已经为此花费了整整一个晚上,我正在寻求帮助。我收到以下错误“函数返回未定义、预期的承诺或值”。我的代码如下。我究竟做错了什么?我还怀疑我必须使用 await/async,因为看起来我的代码正在运行,而无需等待第一次 get 完成。

const admin = require('firebase-admin');
const functions = require('firebase-functions');
var db = admin.firestore();

exports.declinedRequest = functions.firestore
.document('requests/{requestId}')
.onUpdate((change, context) => {
  const newValue = change.after.data();
  const status = newValue.status;
  const request = context.params.requestId;
  var registrationToken;
  var message;

  if(status=="created") {
    console.log('Checkpoint1 ',context.params.requestId);
    newValue.friends.forEach(doc => {
      console.log('Checkpoint 2: ', doc);

      var usersRef = db.collection('users');
      var query = usersRef.where('mobile', '==', doc).get()
        .then(snapshotFriend => {
          if (snapshotFriend.empty) {
            console.log('Checkpoint3.');
            return;
          }  

        snapshotFriend.forEach(mobile => {

        registrationToken = mobile.data().fcmToken;
        console.log('FCM token =>', registrationToken);
        if (!registrationToken) {
          console.log('No fcmToken available');
          return;
        }  
         message = {
          notification: {
            body: "Request still available from " + newValue.requesterName,
            sound: "default", 
            badge: 1
            },
          data: {
            requestId: `${request}`
          }
        };

        console.log('FCM token message created');

        }) 
      })
    })
  } else {
    return;
  }
 return admin.messaging().sendToDevice(registrationToken, message)
      .then(function (response) {
        console.log("Successfully sent message:", response)
     })
      .catch(function (error) {
        console.log("Error sending message:", error);
     }) 

})

【问题讨论】:

  • 主要问题是当函数进入第一个 if 块时,您没有从函数的顶层返回承诺。嵌套在回调和函数中的返回不会从顶层返回。此外,你没有任何义务使用 async/await,因为它只是一种方便的语法,与你使用 then 对 promise 执行的操作相同。
  • 观看 Cloud Functions 上的 this video series 以及如何在其中使用 Promise 可能会有所帮助。它还有助于从一个简单的功能开始,然后再增加复杂性。现在,对于刚接触 node 的人来说,你所拥有的相当复杂。
  • 谢谢你,道格。我看过这个视频系列,但没有遇到任何关于当 if 处于顶层时如何修复它的建议。我根据您的反馈做了一项更改(上面更新了代码)。但是,现在看起来底部的 return 比上面的代码执行得更快。我正在努力在返回之前插入等待。有什么建议吗?

标签: javascript node.js firebase promise google-cloud-functions


【解决方案1】:

试试下面的代码,希望它会起作用。

    const admin = require('firebase-admin');
    const functions = require('firebase-functions');
    const Promise = require('bluebird');
    const _ = require('lodash');
    let db = admin.firestore();

    exports.declinedRequest = functions.firestore
    .document('requests/{requestId}')
    .onUpdate((change, context) => {
        const newValue = change.after.data();
        const status = newValue.status;
        const request = context.params.requestId;
        if (status == "created") {
            console.log('Checkpoint1 ', context.params.requestId);
            allPromises = [];
            newValue.friends.forEach(doc => {
                console.log('Checkpoint 2: ', doc);
                const usersRef = db.collection('users');
                // query for each document return promise.
                allPromises.push(queryForEachDocument(doc,request,usersRef));
            });
            return Promise.all(allPromises);
        } else {
            return Promise.reject / resolve('Whatever you want.');
        }
    })

    function queryForEachDocument(doc,request,usersRef) {
    let promiseInvoices = []
    let registrationToken;
    let message;
    return usersRef.where('mobile', '==', doc).get().then((snapshotFriend) => {
        if (_.isEmpty(snapshotFriend)) {
            console.log('Checkpoint3.');
            return Promise.reject(new Error('Your error'));
        }
        snapshotFriend.forEach(mobile => {
            registrationToken = mobile.data().fcmToken;
            console.log('FCM token =>', registrationToken);
            if (!registrationToken) {
                console.log('No fcmToken available for', newValue.requesterName);
                // Do anything you want to change here.
                return Promise.reject(new Error('No fcmToken available for',newValue.requesterName));
            }
            message = {
                notification: {
                    body: "Request still available from " + newValue.requesterName,
                    sound: "default",
                    badge: 1
                },
                data: {
                    requestId: request
                }
            };
            console.log('FCM token message created');
            // send invoice for each registrationToken
            promiseInvoices.push(sendInvoice(registrationToken, message))
        });
    }).then(() => {
        return Promise.all(promiseInvoices);
    })
    }
    function sendInvoice(registrationToken, message) {
    return admin.messaging().sendToDevice(registrationToken, message)
        .then(function (response) {
            console.log("Successfully sent message:", response)
        })
        .catch(function (error) {
            console.log("Error sending message:", error);
        })
    }

【讨论】:

  • 感谢 Shubham 更正我的代码。它运行良好,但我无法使用 Promise.reject / resolve('Whatever you want.') 部署它。 / 是什么意思?我不得不放弃拒绝和/使其工作。你知道为什么吗?
  • 您可以解决该问题,也可以拒绝两者,这取决于您要做什么。因此,如果成功,您可以解决问题,如果您认为应该有错误,您可以调用拒绝,我无法找到您想要做的确切事情,这就是我写 return Promise.reject / resolve('Whatever you want.') 的原因,您可以写返回Promise.resolve('Whatever you want.')return Promise.reject('Whatever you want.');
猜你喜欢
  • 2020-12-23
  • 2018-06-17
  • 2019-06-09
  • 1970-01-01
  • 2018-09-14
  • 2019-05-11
  • 2018-12-17
  • 2019-11-18
  • 2018-09-03
相关资源
最近更新 更多