【问题标题】:Using Cloud Functions to store data form an external API on Firestore database使用 Cloud Functions 从 Firestore 数据库上的外部 API 存储数据
【发布时间】:2020-01-28 15:18:14
【问题描述】:

我有一个在 Firebase 上运行的 Vue.js 应用程序,我使用 Firestore 作为数据库。该应用程序必须从另一个应用程序 (app2) 导入数据(客户端),但 app2 仅通过通过 POST 将 XML 代码发送到地址来导出。为了从 app2 接收 POST,我的应用使用了 Firebase Cloud Functions。

const xml2js = require("xml2js");
const functions = require("firebase-functions");
const cors = require("cors");
const express = require("express");
const app = express(); 
const admin = require("firebase-admin");

const db = admin.initializeApp().firestore();

function parseXml(xml) {
    return new Promise((resolve, reject) => {
        xml2js.parseString(xml, { explicitArray: false }, (err, result) => {
            if (err) {
                reject(err);
            } else {
                resolve(result);
            }
        });
    });
}

app.use(cors({ origen: true }));
    app.post("/", async (request, response) => {
    let xml = request.body.XMLRecords.toString();
    const clientes = db.collection("clientes");
    xml = xml.replace(/&(?!(?:apos|quot|[gl]t|amp);|#)/g, "&").trim();
    xml = " " + xml;

    console.log("Prep XML:");
    console.log(xml);

    let parsXml = await parseXml(xml);
    console.log("parsXML");
    console.log(parsXml);

    Array.from(parsXml.Records.Clientes.Cliente).forEach(async cli => {
        if (cli !== null) {
            delete cli.$;
            const docRef = clientes.doc(cli.CliCodigo);
            console.log("cli " + cli.CliCodigo);
            console.log(cli);
            const writeResult = await docRef.set(cli);
            console.log("Cliente " + cli.CliCodigo + " salvo");
        }
    });

    response.send("Received.");
});

exports.apiClientes = functions.https.onRequest((request, response) => {
    if (!request.path) {
        request.url = `/${request.url}`; // prepend '/' to keep query params if any
    }
    return app(request, response);
});

应用程序确实收到了请求并且能够处理它,但是当我尝试与 Firestore 数据库通信时,该函数停止发送 console.log()staments 并且不会将数据保存到数据库中。 我做错了什么?

【问题讨论】:

    标签: javascript firebase google-cloud-firestore google-cloud-functions xml2js


    【解决方案1】:

    这很可能是因为在您的 Array.from(parsXml.Records.Clientes.Cliente).forEach() 循环中,您正在执行多个异步 set() 操作,但您正在返回响应 (response.send("Received.");)在这些异步操作完成之前。。 p>

    通过response.send("Received.");,您向运行云函数的实例表明它可以终止它,但在大多数情况下,对 Firestore 的异步写入并未完成。

    需要正确处理set()方法调用返回的Promises,如下(未测试):

    //....
    const promises = [];
    
    Array.from(parsXml.Records.Clientes.Cliente).forEach(cli => {
        if (cli !== null) {
            delete cli.$;   
            const docRef = clientes.doc(cli.CliCodigo);
    
            promises.push(docRef.set(cli));
        }
    });
    
    await Promise.all(promises);
    response.send("Received.");
    //....
    

    因此,我们使用Promise.all() 并行执行所有set() 方法调用。 Promise.all() 方法返回一个 single Promise,当作为可迭代对象(即 promises 数组)传递给的所有承诺都已履行时,该承诺履行。因此,当您发回响应时,您确信所有异步工作都已完成,向 Cloud Function 平台表明它可以安全地终止您的 Cloud Function。

    【讨论】:

    • 这很有道理,这就是日志没有通过的原因。还值得注意的是,异步 forEach 循环很棘手。
    猜你喜欢
    • 1970-01-01
    • 2021-03-29
    • 2021-09-07
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 2021-07-25
    • 1970-01-01
    相关资源
    最近更新 更多