首页 > 解决方案 > 无法使用 https 可调用从云函数返回数据

问题描述

我正在从我的 Angular 应用程序中调用以下云函数,但即使云函数正确记录了结果,返回的值也始终为 null。不知道我做错了什么。

我的角度代码如下:

const data = {test: testToProcess};
const process = this.fns.httpsCallable("gprocess"); // fns is Angular Fire Functions
process(data)
  .toPromise() // since Angular Fire function returns an observable, Iam converting to a promise
  .then(
    (result) => {
      console.log("function called: " + JSON.stringify(result));
    },
    (err) => {
      console.log("Function call error " + JSON.stringify(err));
    }
  );

我的云函数代码如下:

import * as functions from "firebase-functions";
const fs = require("fs");
const { google } = require("googleapis");
const script = google.script("v1");
const scriptId = "MY_SCRIPT_ID";

export const gprocess = functions.https.onCall(async (data: any, context: any) => {
const test = data.test;

return fs.readFile("gapi_credentials.json", (err: any, content: string) => {
  if (err) {return err;}
  const credentials = JSON.parse(content); // load the credentials
  const { client_secret, client_id, redirect_uris } = credentials.web;
  const googleAuth = require("google-auth-library");
  const functionsOauth2Client = new googleAuth.OAuth2Client(client_id, client_secret, redirect_uris); // Constuct an auth client
  functionsOauth2Client.setCredentials({refresh_token: credentials.refresh_token,}); // Authorize a client with credentials
  
  return runScript(functionsOauth2Client,scriptId,JSON.stringify(test))
    .then((scriptData: any) => {
      console.log("Script data in main function is" + JSON.stringify(scriptData));
      return scriptData;
    })
    .catch((error) => {return error;}); 
   });
 });

function runScript(auth: any, scriptid: string, test: any) {
 return new Promise(function (resolve, reject) {
 script.scripts.run({
      auth: auth, 
      scriptId: scriptid,
      resource: {function: "doGet",devMode: true,parameters: test}
    })
  .then((err: any, respons: any) => {
    if (err) {
      console.log("API returned an error: " + JSON.stringify(err));
      resolve(err);
    } else if (respons) {
      console.log("Script is run and response is " + JSON.stringify(respons));
      resolve(respons);
    }
  });
});
}

角度函数在云函数上的处理完成之前返回这个结果。IT 不等待从云功能返回的结果。

detailed.component.ts:691 function called: null

一段时间后,结果会记录在云功能控制台上,但这不会返回给 Angular 客户端。云端日志功能如下,正确的结果如下图所示:

5:53:32.633 PM  gpublish Function execution started
5:53:32.694 PM  gpublish Function execution took 61 ms, finished with status code: 204
5:53:33.185 PM  gpublish Function execution started
5:53:33.804 PM  gpublish Function execution took 620 ms, finished with status code: 200
5:54:31.494 PM  gpublish Script is run and response is : {"config":... some result}
5:54:31.593 PM  gpublish Script data in main function is{"config":... some result}

请帮忙!

标签: javascriptnode.jsfirebasegoogle-cloud-functionsangularfire2

解决方案


您的函数未正确返回解析为要序列化并发送给客户端的数据的承诺。问题是fs.readFile实际上并没有返回一个承诺。它是异步的,不返回任何内容,这就是客户端将收到的内容。正在调用回调,但该回调中的任何内容都不会影响客户端看到的内容。

您将需要找到另一种方式来执行文件 I/O,或者是同步的(例如fs.readFileSync),或者实际上使用 Promise 而不是仅仅使用异步回调。


推荐阅读