【问题标题】:Firebase Callable Cloud Function is returning void without a Promise in some cases在某些情况下,Firebase 可调用云函数在没有 Promise 的情况下返回 void
【发布时间】:2021-12-05 22:44:23
【问题描述】:

当调用 firebase 可调用云函数时:

const myFunctions = require('/path/to/functions/src/index.js');

 myFunctions.myTestFunc(data, {
       auth: {
         uid: myId
       }
     }).then(r => {
      console.log("THIS IS THE ACTUAL RESPONSE FROM CLOUD FUNCTION", r);

     })

我得到: 类型“void |”上不存在属性“then”承诺'。类型“void”上不存在属性“then”。

即使有问题的可调用函数显然返回了一个已解决的 Promise:

export const myTestFunc = functions.https.onCall(
  async (data, context) => {

     return new Promise((resolve) => {
      resolve({success: true});
    });
        
  });

它仍然给出警告: const myTestFunc: (req: e.Request, resp: e.Response) => void |承诺

本质上是说在某些情况下会返回 void。但是,当我明确返回上述承诺时,我看不到情况如何。

任何关于正在发生的事情的想法将不胜感激。

【问题讨论】:

  • 尝试深入了解 onCall 方法的定义。打字稿绑定说它返回什么?这就是你得到的,不管你作为处理函数传递什么。

标签: typescript firebase google-cloud-functions


【解决方案1】:

如果您导航到onCall() 的源代码,您会看到它是这样定义的:

export declare function onCall(
    handler: (data: any, context: CallableContext) => any | Promise<any>
): HttpsFunction & Runnable<any>;

你会收到一个HttpsFunction,它是这样的:

export declare type HttpsFunction =
    TriggerAnnotated & ((req: Request, resp: Response) => void | Promise<void>);

可以看到函数类型的返回类型是void | Promise&lt;void&gt;。它不关心你传递给它什么,这就是你得到的——一个接受RequestResponse并返回void | Promise&lt;void&gt;的函数。

如果您需要调用该函数并且想知道它是否返回了可以调用 then 的承诺(而不是 void),那么您需要检查它是否返回了非 void 的内容,并且它将假设 Promise:

const p = myFunctions.myTestFunc(req, res);
if (p) {
    p.then(...)
}

看来您可能想查看testing HTTP functions 的文档,如果这就是您要在此处执行的操作。一般没有理由直接调用onCall 返回的函数。有一个测试库可以帮助解决这个问题。

如果您尝试为自己创建一个可重用的实用程序函数,那么您根本不应该使用 onCall。只需定义并导出您的普通 JavaScript 函数,以供任何调用方导入使用。

【讨论】:

  • 我要强调的是,这里应该使用firebase-functions-testwrap(exportedCloudFunction) 方法。 onCall 函数是 background function,但与其他一些后台函数一样,它们是真正的 HTTPS 请求函数,具有对 CORS、有效负载和身份验证的特殊处理,以便于使用,wrap() 方法对此进行欺骗以进行测试。 (链接是 OP,不是你 doug :D)
  • 那么让我为我的目的问一个更实际的问题。我目前正在测试,但最终尝试使用此 onCall 云功能在从 Ionic 4 应用程序中的服务调用时执行一些数据库(云火库)更新。因此,我需要检查数据和上下文。在我的情况下,这个云功能可以简化(省略数据库更新),如下所示:
  • export const myTestFunc = functions.https.onCall( (data: any, context: functions.https.CallableContext) => { return new Promise((resolve, reject) => { if (data &&上下文 && context.auth && context.auth.uid) { resolve({success: true}); } else { reject({success: false}); } }); });
  • 但最终你明白了:我试图将成功消息包装在一个承诺中,然后在我的测试代码中返回该消息时对其进行测试。从您上面的回答来看,这似乎不像我想象的那样可行。我真的很想要一种从我的函数传回成功消息的方法。有什么方法可以从可调用函数中做到这一点,还是我会被困在使用具有该响应对象的 onRequest 云函数中?
  • 您可以将任何您想要的内容放入响应的有效负载中。它只是一个被序列化为 JSON 的 JS 对象。您应该使用提供的测试库进行设置。
猜你喜欢
  • 2015-08-03
  • 1970-01-01
  • 2016-09-08
  • 1970-01-01
  • 2018-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多