【问题标题】:Firebase: Calling Cloud Function From Cloud FunctionFirebase:从云函数调用云函数
【发布时间】:2019-01-18 23:57:53
【问题描述】:

我遇到了 Firebase 云功能的问题。我有一个触发一系列事件的 onWrite 云函数。我有一个与 onWrite 云函数绑定的请求的路径。当该云函数执行时,它会删除请求路径的新请求,并将请求推送到渲染路径/队列,该路径/队列将用于客户端渲染 UI 元素/数据。将数据写入渲染路径后,我会调用一个与任何云事件无关的 vanilla javascript 函数。 vanilla javascript 函数应该与外部 API 联系并获取一些数据,以便稍后在推送到渲染路径的渲染对象上进行更新。

问题在于 vanilla javascript 函数永远不会执行。我一直在网上寻找为什么会发生这种情况,但似乎无法弄清楚为什么。我在 Flame 计划中,因此据我所知,应该允许出站 api 请求。这是我的代码示例:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const request = require('request');
admin.initializeApp();


exports.requestModule = functions.database.ref('/requests').onWrite((change, context) => {
  // Create reference to database
  let db = admin.database();

  if (context && context.auth && context.auth.uid) {
    const afterData = change.after.val();
    let uid = context.auth.uid;
    let cleanData = afterData[uid];
    cleanData.status = "loading";

    // Remove the requested module from the requests path
    let cleansePath = db.ref('/requests/' + uid);
    cleansePath.remove().then((snapshot) => {
      return true;
    }).catch((error) => {
      console.log(error);
      return false;
    });

    // Add requested module to the render path
    let renderPath = db.ref('/render/' + uid);
    renderPath.push(cleanData).then((snapshot) => {
      let val = snapshot.val();
      let key = snapshot.key;
      // Trigger the get weather api call
      getWeather(uid, key, val);
      return true;
    }).catch((error) => {
      console.log(error);
      return false;
    });
  }
});

// Fetches data from external api
function getWeather (uid, key, obj) {
  console.log('Fetching weather!');
  let db = admin.database();
  request('https://api.someweathersite.net/forecast/', (error, response, body) => {
    if (!error && Number(response.statusCode) === 200) {
      console.log('error:', error); 
      console.log('statusCode:', response && response.statusCode); 
      console.log('body:', body); 
      obj.data = body;
      obj.status = 'loaded';
      // Set data from api response in render object to be shown client side
      let render = db.ref('/render/' + uid + '/' + key );
      render.set(obj).then(() => {
        return true;
      }).catch((error) => {
        console.log(error)
        return false;
      });
    }
  });
}

“getWeather”函数顶部的 console.log 消息永远不会执行。我认为“getWeather”函数从未执行过。

如果我将 api 调用直接放在 onWrite "requestModule" 函数中,则 api 调用将起作用。但是,当它调用外部函数时,它永远不会被调用/工作。我基本上想让“requestModule”函数处理所有请求,并计划有一个模块调度程序来处理应该从中获取哪个模块函数/api数据。这就是为什么我不想将 api 调用保留在“requestModule”函数中。知道为什么会发生这种情况或我如何才能让它发挥作用吗?

【问题讨论】:

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


    【解决方案1】:

    getWeather 正在执行异步工作以获取一些数据,但它没有返回一个承诺来指示该工作何时完成。事实上,您在这里执行的所有异步工作都没有正确使用各种 API 调用返回的承诺。在每个 promise 上简单地使用 then() 是不够的。

    您需要跟踪所有异步工作,并返回一个仅在所有工作完成后才解析的承诺。否则,Cloud Functions 可能会在工作完成之前终止并清理您的函数。 (请注意,在强制终止之前哪些工作可能会或可能不会实际完成并不确定,但确保所有工作完成的唯一方法是通过您返回的单一承诺。)

    您可能想观看我关于在 Cloud Functions 中使用 Promise 的教程,以更好地了解您需要做什么才能使您的函数正常工作:https://firebase.google.com/docs/functions/video-series/

    【讨论】:

    • 谢谢道格!非常感激。现在正在观看视频系列。对我来说很有意义。
    猜你喜欢
    • 1970-01-01
    • 2019-06-01
    • 2018-05-17
    • 2021-09-13
    • 2021-02-10
    • 2017-08-09
    • 2019-07-29
    • 1970-01-01
    • 2017-08-04
    相关资源
    最近更新 更多