我遇到了Firebase云功能的问题。我有一个onWrite云函数,它会触发一系列事件。我有一个将onWrite云功能绑定到的请求的路径。当该云功能执行时,它将删除对请求路径的新请求,并将该请求推入到呈现路径/ que中,该路径/ que将在客户端用于呈现UI元素/数据。将数据写入渲染路径后,我将调用不与任何云事件绑定的普通javascript函数。普通的javascript函数应该可以访问外部API,并获取一些数据,以便稍后在推送到渲染路径的渲染对象上进行更新。
问题是香草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”函数中的原因。关于为什么发生这种情况或如何使它起作用的任何想法吗?
答案 0 :(得分:3)
getWeather
正在执行异步工作以获取一些数据,但没有返回承诺来指示该工作何时完成。实际上,您在此处执行的所有异步工作均未正确使用各种API调用返回的promise。仅在每个promise上使用then()
是不够的。
您需要跟踪所有异步工作,并返回仅在所有工作完成后才能解决的单个承诺。否则,云功能可能会终止并在工作完成之前清理您的功能。 (请注意,并不确定在强制终止之前哪个工作可能会或可能不会真正完成,但是确保所有工作完成的唯一方法是通过您返回的那个承诺。)
您可能希望观看我的有关在Cloud Functions中使用Promise的教程,以更好地了解使功能正常运行所需的操作:https://firebase.google.com/docs/functions/video-series/