如何将外部请求的结果推送到Firebase中的realtimeDB?

时间:2019-04-14 15:37:48

标签: node.js firebase firebase-realtime-database soap google-cloud-functions

我正在尝试发出SOAP请求,并将结果推送到Firebase数据库。

我编写了一个函数,当使用节点index.js进行控制台调用时,该函数可以正常工作。记录我的SOAP请求的结果。

我有一个在HTTPS请求上触发的firebase函数。该函数调用我的,但是没有数据被推送到数据库。

function getStopData(){
  (async () => {
    const { response } = await soapRequest(url, headers, xml); // Optional timeout parameter(milliseconds)
    const { body, statusCode } = response;

    parseString(body, function (err, result) {
        var envelope = result['soap:Envelope'];
        var body = envelope['soap:Body'];
        var result = body.pop();
        var resultXml = result.GetRealTimeStopDataResponse.pop().GetRealTimeStopDataResult.pop()

        var stopData = resultXml['diffgr:diffgram'].pop().DocumentElement.pop().StopData;
        var busses = []
        for (bus in stopData) {
          delete stopData[bus].$
          busses.push(stopData[bus]);
        }
        admin.database().ref('/test14').push({testText: 'test14Text'});
    });
  })();
}

admin.initializeApp();

exports.test14 = functions.region('europe-west1')
.https.onRequest(async (req, res) => {
  getStopData(); //Runs function, but no test is pushed to DB
  admin.database().ref('/test14').push({testText: 'test14Text'}); //This is pushed to dB
  return res.send("Success");
});

测试字符串被火力函数推入。常规函数中的测试字符串不是。

谢谢。

如果firebase不适合此应用程序,请提出其他建议。我试图创建一个每2分钟运行一次的函数来发出SOAP请求并存储结果。

编辑:根据第一个答案,我已经修改了我的代码以匹配建议的代码。这给我带来了另一个错误。

 5:25:49.623 PM
test14
SOAP FAIL: Error: timeout of 10000ms exceeded

5:25:49.624 PM
test14
Unhandled rejection

5:25:49.624 PM
test14
Error: timeout of 10000ms exceeded at createError (/srv/node_modules/axios-https-proxy-fix/lib/core/createError.js:16:15) at Timeout.handleRequestTimeout [as _onTimeout] (/srv/node_modules/axios-https-proxy-fix/lib/adapters/http.js:216:16) at ontimeout (timers.js:498:11) at tryOnTimeout (timers.js:323:5) at Timer.listOnTimeout (timers.js:290:5)

5:25:49.631 PM  
test14
Function execution took 10712 ms, finished with status: 'crash' 

我不确定为什么会出现SOAP Fail,因为与节点index.js一起运行仍会产生正确的数据记录到控制台。

  MonitoredVehicleJourney_Monitored: [ 'true' ],
    MonitoredVehicleJourney_InCongestion: [ 'false' ],
    MonitoredVehicleJourney_BlockRef: [ '37006' ],
    MonitoredVehicleJourney_VehicleRef: [ '44138' ],
    MonitoredCall_VisitNumber: [ '4' ],
    MonitoredCall_VehicleAtStop: [ 'false' ],
    MonitoredCall_AimedArrivalTime: [ '2019-04-14T18:19:45+01:00' ],
    MonitoredCall_ExpectedArrivalTime: [ '2019-04-14T18:19:45+01:00' ],
    MonitoredCall_AimedDepartureTime: [ '2019-04-14T18:19:45+01:00' ],
    MonitoredCall_ExpectedDepartureTime: [ '2019-04-14T18:19:45+01:00' ],
    Timestamp: [ '2019-04-14T17:34:14.97+01:00' ],
    LineNote: [ '' ] } ]

1 个答案:

答案 0 :(得分:0)

在Cloud Functions上运行代码时,需要支付运行时间。因此,在您将响应发送回调用客户端之后,使用return res.send("Success"),Cloud Functions运行时将立即终止容器。

但是您的SOAP调用是异步发生的,并且在res.send运行之后继续。在这种情况下,您必须告诉Cloud Functions完成时间。由于您不这样做,因此Cloud Functions可以随时终止运行代码的容器,显然在这种情况下,这是在SOAP请求完成之前发生的。

解决方案是仅在SOAP调用的结果返回时才编写响应:

function getStopData(){
  (async () => {
    const { response } = await soapRequest(url, headers, xml); // Optional timeout parameter(milliseconds)
    const { body, statusCode } = response;

    parseString(body, function (err, result) {
        var envelope = result['soap:Envelope'];
        var body = envelope['soap:Body'];
        var result = body.pop();
        var resultXml = result.GetRealTimeStopDataResponse.pop().GetRealTimeStopDataResult.pop()

        var stopData = resultXml['diffgr:diffgram'].pop().DocumentElement.pop().StopData;
        var busses = []
        for (bus in stopData) {
          delete stopData[bus].$
          busses.push(stopData[bus]);
        }
        admin.database().ref('/test14').push({testText: 'test14Text'}).then(() => {
          res.send("Success");
        });
    });
  })();
}

admin.initializeApp();

exports.test14 = functions.region('europe-west1')
.https.onRequest(async (req, res) => {
  getStopData(res);
});