问题
I am trying to set up a firebase cloud function that regularly makes an api call to the Feedly API.
However, it is not working and I'm not sure why. Here is the code:
const functions = require('firebase-functions')
const express = require('express')
const fetch = require('node-fetch')
const admin = require('firebase-admin')
admin.initializeApp()
const db = admin.firestore()
const app = express()
exports.getNewsArticles = functions.pubsub
.schedule('every 5 minutes')
.onRun(() => {
app.get('/feedly', async (request, response) => {
const apiUrl = `https://cloud.feedly.com/v3/streams/contents?streamId=user/[USER_ID_NUMBER]/category/global.all&count=100&ranked=newest&newThan=300000`
const fetchResponse = await fetch(apiUrl, {
headers: {
Authorization: `Bearer ${functions.config().feedly.access}`
}
})
const json = await fetchResponse.json()
json.items.forEach(item => {
db.collection('news').add({
status: 'pending',
author: item.author || '',
content: item.content || '',
published: item.published || '',
summary: item.summary || '',
title: item.title || '',
})
})
})
})
Any idea what I need to do to get this to work?
回答1:
There are potentially three problems in your Cloud Function:
1. You are mixing up the code for Schedule Functions with the one of HTTPS Functions
Have a look at the doc for Schedule Functions and HTTPS Functions. In a Schedule Function, you should not use app.get()
and just do, for example:
exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) => {
console.log('This will be run every 5 minutes!');
return null;
});
2. You must return a Promise (or a value)
You must return a Promise (or a value) in your Cloud Function, to indicate to the platform that the Cloud Function has completed. In case the tasks in the Cloud Function are synchronous you can just return a a value, e.g. return null;
as shown in the example above. In case one or more tasks are asynchronous you must return a Promise.
So, in your case you need to use Promise.all() as follows, since you are executing several (asynchronous) writes in parallel:
exports.getNewsArticles = functions.pubsub
.schedule('every 5 minutes')
.onRun((context) => {
const apiUrl = `https://cloud.feedly.com/v3/streams/contents?streamId=user/[USER_ID_NUMBER]/category/global.all&count=100&ranked=newest&newThan=300000`
const fetchResponse = await fetch(apiUrl, {
headers: {
Authorization: `Bearer ${functions.config().feedly.access}`
}
})
const json = await fetchResponse.json()
const promises = [];
json.items.forEach(item => {
promises.push(
db.collection('news').add({
status: 'pending',
author: item.author || '',
content: item.content || '',
published: item.published || '',
summary: item.summary || '',
title: item.title || '',
}))
})
return Promise.all(promises)
})
3. You may need to upgrade your pricing plan
You need to be on the "Flame" or "Blaze" pricing plan.
As a matter of fact, the free "Spark" plan "allows outbound network requests only to Google-owned services". See https://firebase.google.com/pricing/ (hover your mouse on the question mark situated after the "Cloud Functions" title)
Since the Feedly API is not a Google-owned service, you may need to switch to the "Flame" or "Blaze" plan.
来源:https://stackoverflow.com/questions/59346203/google-cloud-functions-cron-job-for-api-call