无法使用 https callable return 来自云函数的数据
Unable to return data from cloud function using https callable
我正在从我的 Angular 应用程序调用以下云函数,但返回的值始终为 null,即使云函数正确记录了结果。不确定我做错了什么。
我的Angular代码如下:
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);
}
});
});
}
angular 函数在完成对云函数的处理之前返回此结果。 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}
请帮忙!
您的函数未正确return承诺解析数据以序列化并发送给客户端。问题是 fs.readFile 实际上 return 并不是一个承诺。它是异步的,return什么都没有,这就是客户端将收到的内容。正在调用回调,但回调中的任何内容都不会影响客户端看到的内容。
您将需要找到另一种处理文件的方法 I/O,它可以是同步的(例如 fs.readFileSync),也可以实际使用 promises 而不仅仅是异步回调。
如上所述,我更改了代码以使用 readFileSync(谢谢 Doug!)
此外,我对从云函数发送回 Angular 客户端的数据进行了字符串化处理。
我的云函数现在看起来像这样:
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) => {
try {
const test = data.test;
const content = fs.readFileSync("credentials.json"); // CHANGED TO READFILESYNC
const credentials = JSON.parse(content);
const { client_secret, client_id, redirect_uris } = credentials.web;
const googleAuth = require("google-auth-library");
const functionsOauth2Client = ... some code to construct an auth client and authorise it
return runScript(functionsOauth2Client,scriptId,JSON.stringify(test)).then((scriptData: any) => {
return JSON.stringify(scriptData); // STRINGIFIED THE DATA
});
} catch (err) {
return JSON.stringify(err);
}
});
function runScript(auth: any, scriptid: string, test: any) {
return new Promise(function (resolve, reject) {
script.scripts.run({auth: auth,scriptId: scriptid,resource: {function: "doGet",parameters: test}})
.then((respons: any) => {resolve(respons.data);})
.catch((error: any) => {reject(error);});
});
}
我正在从我的 Angular 应用程序调用以下云函数,但返回的值始终为 null,即使云函数正确记录了结果。不确定我做错了什么。
我的Angular代码如下:
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);
}
});
});
}
angular 函数在完成对云函数的处理之前返回此结果。 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}
请帮忙!
您的函数未正确return承诺解析数据以序列化并发送给客户端。问题是 fs.readFile 实际上 return 并不是一个承诺。它是异步的,return什么都没有,这就是客户端将收到的内容。正在调用回调,但回调中的任何内容都不会影响客户端看到的内容。
您将需要找到另一种处理文件的方法 I/O,它可以是同步的(例如 fs.readFileSync),也可以实际使用 promises 而不仅仅是异步回调。
如上所述,我更改了代码以使用 readFileSync(谢谢 Doug!) 此外,我对从云函数发送回 Angular 客户端的数据进行了字符串化处理。
我的云函数现在看起来像这样:
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) => {
try {
const test = data.test;
const content = fs.readFileSync("credentials.json"); // CHANGED TO READFILESYNC
const credentials = JSON.parse(content);
const { client_secret, client_id, redirect_uris } = credentials.web;
const googleAuth = require("google-auth-library");
const functionsOauth2Client = ... some code to construct an auth client and authorise it
return runScript(functionsOauth2Client,scriptId,JSON.stringify(test)).then((scriptData: any) => {
return JSON.stringify(scriptData); // STRINGIFIED THE DATA
});
} catch (err) {
return JSON.stringify(err);
}
});
function runScript(auth: any, scriptid: string, test: any) {
return new Promise(function (resolve, reject) {
script.scripts.run({auth: auth,scriptId: scriptid,resource: {function: "doGet",parameters: test}})
.then((respons: any) => {resolve(respons.data);})
.catch((error: any) => {reject(error);});
});
}