#node.js #firebase #firebase-realtime-database #google-cloud-functions
#node.js #firebase #firebase-база данных в реальном времени #google-cloud-функции
Вопрос:
Я получаю объект, у которого есть список идентификаторов продуктов и ссылка на его базу данных, поэтому я должен искать каждый продукт в своей базе данных, чтобы получить его цену, я пробовал что-то вроде этого
const functions = require('firebase-functions');
const cors = require('cors')({
origin: true
});
const admin = require('firebase-admin');
var request = require('request');
admin.initializeApp();
exports.GeraPagSeguro = functions.https.onRequest((req, res) => {
cors(req, res, () => {
if (req.method === 'POST') {
var xml;
req.body.map((product) => {
admin.database().ref(product.refitem).once('value', (snapshot) => {
const value = snapshot.val();
const price = value.price;
xml = price;
//rest of code building the xml i want
})
})
//rest of code sending the xml via POST to other server
})
})
})
Проблема в том, что остальная часть кода не wait
выполняет все обещания map
.
Комментарии:
1. Я так не думаю, я вроде как новичок в node.js и firebase, req.body — это просто обычный объект javascript
2. Мой плохой, я принял это за что-то другое, ознакомьтесь с моим ответом
Ответ №1:
Чтобы дождаться завершения нескольких асинхронных операций, используйте Promise.all()
:
var xml;
var promises = [];
req.body.map((product) => {
promises.push(admin.database().ref(product.refitem).once('value', (snapshot) => {
const value = snapshot.val();
const price = value.price;
return price;
})
})
Promise.all(promises).then((prices) => {
prices.forEach((price) => {
...
});
//rest of code sending the xml via POST to other server
});
Комментарии:
1. Когда я пытаюсь развернуть функцию, я получаю сообщение об ошибке
Parsing error: Unexpected token Promise
в этой строкеlet prices = await Promise.all(promises)
2. Интересно. Возможно, вы захотите попробовать это с
Promise.all(promises).then(prices => {});
вместо этого.3. @FrankvanPuffelen по умолчанию асинхронные функции не включены в настройках Firebase functions, вы должны указать некоторые вещи в файле конфигурации, чтобы заставить его работать. Смотрите мой ответ
4. Использование
Promise.all(promises).then(prices => {});
сработало, спасибо5. ОК. Обновлено, чтобы отразить это. Возможно, вы не можете использовать
await
на верхнем уровне или вам не хваталоasync
аннотации к самому объявлению функции. Честно говоря: я используюPromise.then()
еще больше, поэтому не полностью привык кasync
/await
облачным функциям.
Ответ №2:
Поскольку функция базы данных firebase возвращает Promise
, вы можете превратить свою функцию в асинхронную функцию и вызвать await
ее. Вот так:
exports.GeraPagSeguro = functions.https.onRequest(async (req, res) => {
cors(req, res, () => {
if (req.method === 'POST') {
var xml;
req.body.map((product) => {
const snapshot = await admin.database().ref(product.refitem).once('value')
const value = snapshot.val();
const price = value.price;
xml = price;
//rest of code building the xml i want
})
//rest of code sending the xml via POST to other server
})
})
})
Затем вы можете выполнить другой код, как будто они «ждали» операции firebase
Примечание: Асинхронные функции не включены в настройках Firebase functions по умолчанию, вам необходимо указать emcaVersion
значение 2017 или 8 (по умолчанию 7) в .eslintrc.json
файле, чтобы убедиться, что связанные с асинхронностью функции работают. Это должно выглядеть так:
{
"parserOptions": {
"ecmaVersion": 2017 //or 8
}
}
Кроме того, вам также нужно добавить promise
в качестве плагина, вот так:
"plugins": [
"promise"
]
Если у вас есть что-либо в, .eslintrc.json
что указывает es6
на использование, измените это на es7
.
Комментарии:
1. Кажется, я не мог использовать это
async function
, потому что я не использовал ` «engines»: { «node»: «8» }` в моем package-json, но теперь я получаю эту ошибкуParsing error: Unexpected token admin
2. Я также получал эту ошибку раньше, вам нужно иметь
"parserOptions": { "ecmaVersion": 2017 }
в вашем.eslintrc.json
файле, чтобы заставить асинхронную работу3. также добавьте
"plugins": [ "promise" ],
4. мой .eslintrc.json также имеет
"plugins": [ "promise" ]
5. кроме того, есть ли у вас что-нибудь вроде env, указывающее es6?