javascript - 使用 Cloud Functions 将来自外部 API 的数据存储在 Firestore 数据库上

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

我有一个在 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() 语句,并且不会保存数据到数据库。 我做错了什么?

最佳答案

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

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

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

//....
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() 方法返回一个单个 Promise,当所有作为可迭代对象传递的 Promise(即 promises 数组)都满足时,该 Promise 就会被满足。已实现。因此,当您发送回响应时,您可以确定所有异步工作都已完成,向云函数平台表明它可以安全地终止您的云函数。

关于javascript - 使用 Cloud Functions 将来自外部 API 的数据存储在 Firestore 数据库上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59951851/

相关文章:

javascript - 我对这个递归 JavaScript 函数做错了什么?

javascript - 将对象数据添加到现有的 Firebase 文档

swift - 使用 swift 从 firebase 那里的位置获取帖子

firebase - Firestore 查询子集合

javascript - 我有一个想要搜索 Cloud Firestore 的体育项目(数组)列表。但是,数组的大小会有所不同

javascript - 如何在 firestore 中的集合中的数组上应用过滤器

javascript - 如何将Javascript字符串编码为与Libre Barcode 128一起使用的code128?

javascript - 在加载时无需事件即可将数据从子级传递到父级,这在 vue 世界中可能吗?

javascript - Intersection Observer 不适用于 jQuery UI 对话框

firebase - 无法更改 flutter 的功能区域