Javascript 无法使用https callable从云函数返回数据
我正在从Angular应用程序调用以下云函数,但返回的值始终为null,即使云函数正确地记录了结果。我不确定我做错了什么 我的角度代码如下:Javascript 无法使用https callable从云函数返回数据,javascript,node.js,firebase,google-cloud-functions,angularfire2,Javascript,Node.js,Firebase,Google Cloud Functions,Angularfire2,我正在从Angular应用程序调用以下云函数,但返回的值始终为null,即使云函数正确地记录了结果。我不确定我做错了什么 我的角度代码如下: const data = {test: testToProcess}; const process = this.fns.httpsCallable("gprocess"); // fns is Angular Fire Functions process(data) .toPromise() // since Angular Fi
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);
}
});
});
}
我的云功能代码如下:
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);
}
});
});
}
角度函数在云函数处理完成之前返回此结果。它并不等待从云函数返回结果
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}
请帮忙 函数未正确返回解析为要序列化并发送到客户端的数据的承诺。问题是这实际上并没有回报一个承诺。它是异步的,不返回任何内容,这就是客户端将收到的内容。正在调用回调,但回调中的任何内容都不会影响客户端看到的内容
您将需要找到另一种执行文件I/O的方法,这种方法可以是同步的(例如),也可以使用承诺,而不仅仅是异步回调。如上所述,我将代码更改为使用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);});
});
}
与同步方法相比,我们应该更喜欢同步方法吗?我知道在这种情况下没有什么不同,但我猜你的建议是不要在服务器上任何我们不需要的地方阻塞。这完全取决于你。不管是哪种方式,您都必须等待文件被读取。谢谢,这帮了大忙!很高兴听到。在堆栈溢出时,通常使用答案左侧的复选标记图标将有用的答案视为正确答案。感谢您让我知道。