Использование облачных функций для хранения данных из внешнего API в базе данных Firestore - PullRequest
0 голосов
/ 28 января 2020

У меня есть приложение Vue. js, работающее на Firebase, и в качестве базы данных я использую Firestore. Приложение должно импортировать данные (клиенты) из другого приложения (app2), но app2 экспортирует только путем отправки кода XML через POST на адрес. Чтобы получить POST от app2, мое приложение использует функции Firebase Cloud.

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() ставит и не сохраняет данные в базу данных. Что я делаю не так?

1 Ответ

3 голосов
/ 28 января 2020

Скорее всего, это потому, что в Array.from(parsXml.Records.Clientes.Cliente).forEach() l oop вы выполняете несколько асинхронных set() операций, но возвращаете ответ (response.send("Received.");) до того, как эти асинхронные операции будут выполнены .

Делая response.send("Received.");, вы указываете экземпляру, выполняющему вашу облачную функцию, что он может прекратить ее, но в большинстве случаев асинхронная запись в Firestore не завершена.

Вам необходимо правильно обрабатывать обещания, возвращаемые вызовами метода set(), следующим образом (не проверено):

//....
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), были выполнены. Поэтому вы уверены, что вся асинхронная работа выполняется при отправке ответа, указывающего платформе облачных функций, что он может безопасно завершить вашу облачную функцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...