功能完成之前返回Firebase云功能

时间:2019-03-07 09:22:57

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

我上传了一个云函数来对数据库中的多个位置执行更新操作。

当我上传它时,它工作正常,但突然停止工作,并且在HTTP中,它只是返回了{}

我再次查看我的代码,发现现在函数正在返回自身{} 在功能结束之前。

我不知道突然发生了什么事,这破坏了我的整个申请。

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const serviceAccount = require('./myapp.json');
admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: 'https://myapp-b2365.firebaseio.com'
});

exports.quarter = functions.https.onRequest((req, res) => {
     userType1 = admin.database().ref('users/Type1').once('value');
     userType2 = admin.database().ref('users/Type2').once('value');
     userType3 = admin.database().ref('users/Type3').once('value');
     userType4 = admin.database().ref('users/Type4').once('value');
    app_con = admin.database().ref('app_con').once('value');
     Promise.all([userType1, userType2, userType3, userType4, app_con]).then(result => {
        console.log(0);
        result[0].forEach(action => {
            action.ref.update({
                'AverageRating': (action.val().Rating  + action.val().AverageRating )/2,
                'Rating': 0
            })
        });
         console.log(1);
        result[1].forEach(action => {
             action.ref.update({
                 'AverageRating': (action.val().Rating  + action.val().AverageRating  )/2,
                 'Rating': 0
             })
         });
        console.log(2);
        result[2].forEach(action => {
            action.ref.update({
                'Rating': 0
            })
        });
         console.log(3);
        result[3].forEach(action => {
            action.ref.update({
                'Rating': 0
            })
        });
        let q = result[4].val().quarter;
        let y = result[4].val().year;
        if (q === 4) {
            q = 1;
            y = y+1;
        } else {
            q = q+1;
        }
        console.log(4);
        result[4].ref.update({
            'quarter': q,
            'year' : y
        })
       return res.send('Done');
    }).catch(error => {
        return res.status(500).send(error);
    })
});

有趣的是,我只看到

的4个console.log()
info: User function triggered, starting execution
info: 0
info: 1
info: 2
info: Execution took 291 ms, user function completed successfully

我不知道发生了什么,怎么可能??

2 个答案:

答案 0 :(得分:1)

您的函数具有许多异步代码,并且它不会等待所有操作完成才退出。

您可以通过返回承诺并仅在一切完成后解决它来解决此问题,如下所示:

exports.quarter = functions.https.onRequest((req, res) => {
  // return a promise so that the function will wait for it to resolve before exiting
  return new Promise((resolve, reject) => {
    userType1 = admin.database().ref('users/Type1').once('value');
    userType2 = admin.database().ref('users/Type2').once('value');
    userType3 = admin.database().ref('users/Type3').once('value');
    userType4 = admin.database().ref('users/Type4').once('value');
    app_con = admin.database().ref('app_con').once('value');
    const promises = [];
    Promise.all([userType1, userType2, userType3, userType4, app_con]).then(result => {
      console.log(0);
      result[0].forEach(action => {
        // add each async operation to a promise so that you can wait for them
        promises.push(action.ref.update({
          'AverageRating': (action.val().Rating + action.val().AverageRating) / 2,
          'Rating': 0
        }));
      });
      console.log(1);
      result[1].forEach(action => {
        promises.push(action.ref.update({
          'AverageRating': (action.val().Rating + action.val().AverageRating) / 2,
          'Rating': 0
        }));
      });
      console.log(2);
      result[2].forEach(action => {
        promises.push(action.ref.update({
          'Rating': 0
        }));
      });
      console.log(3);
      result[3].forEach(action => {
        promises.push(action.ref.update({
          'Rating': 0
        }));
      });
      let q = result[4].val().quarter;
      let y = result[4].val().year;
      if (q === 4) {
        q = 1;
        y = y + 1;
      } else {
        q = q + 1;
      }
      console.log(4);
      promises.push(result[4].ref.update({
        'quarter': q,
        'year': y
      }));
      // wait for all promises created
      Promise.all(promises).then(() => {
        // only after everything completes you can resolve the promise, which causes the function to exit
        resolve(res.send('Done'));
      }).catch((error) => {
        throw error;
      });
    }).catch(error => {
      reject(res.status(500).send(error));
    })
  });
});

答案 1 :(得分:0)

里卡多·斯马尼亚(Ricardo Smania)完全正确:您必须使用promises(在您的情况下为private String merchantId; private String serialNumber; private String equipmentCode; private String equipmentCodeDesc; private String provisionedDeviceType; private boolean boarded; private boolean provisioned; ),以便等待所有异步工作完成后再发送回响应。

下面的里卡多代码改编应该起作用:

ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
String str = "{\"id\":\"5ZTFCGXQKVZNA\",\"name\":\"xxxx\",\"website\":\"https://xxxx.io\",\"isBillable\":true,\"equipment\":{\"elements\":[{\"merchantId\":\"5ZTFCGXQKVZNA\",\"boarded\":false,\"provisioned\":true,\"serialNumber\":\"C030UQ71040182\",\"equipmentCode\":\"105J\",\"equipmentCodeDesc\":\"Clover Mini\",\"provisionedDeviceType\":\"MAPLECUTTER\"},{\"merchantId\":\"5ZTFCGXQKVZNA\",\"boarded\":false,\"provisioned\":true,\"serialNumber\":\"C050UQ75150054\",\"equipmentCode\":\"1297\",\"equipmentCodeDesc\":\"Clover Station 2018\",\"provisionedDeviceType\":\"GOLDENOAK\"}]}}";
CloverMerchant cv = mapper.readValue(str, CloverMerchant.class);
System.out.println(cv.getId()); //5ZTFCGXQKVZNA
System.out.println(cv.getEquipment().getElements().size()); //2

我建议您观看以下官方视频系列,以了解更多详细信息:https://firebase.google.com/docs/functions/video-series/(尤其是3个视频中的第一个视频,名称为“ Learn JavaScript Promises”)。