Я разрабатываю для Firebase Cloud Functions. У меня есть база данных Firebase Realtime, например:
----- myData
-------eqewrwrepere (this one is a device token)
---------Lta+sde-fer (this one is a firebase id)
firstvalue : "a"
secondvalue : "b"
----------Qrgd+ad-qdda (this one is second firebase id)
firstvalue : "c"
secondvalue : "d"
-------eqwerSAsdqe (this one is another device token)
---------Lta+sde-fer (this one is a firebase id)
firstvalue : "x"
secondvalue : "y"
----------Qrgd+ad-qdda (this one is second firebase id)
firstvalue : "z"
secondvalue : "t"
Я получаю эти данные по этому коду. С помощью этого кода я извлекаю все данные и помещаю их в массив. И когда выборка завершена, я зацикливаю этот массив для поиска элементов. Я разработчик iOS, поэтому я новичок в NodeJS. Вот что я хочу сделать:
firstvalue для каждой базы данных.Теперь я могу извлекать элементы базы данных из своего массива. Когда я делаю запрос в цикле for, запрос называется async. Таким образом, цикл for продолжается, но ответ на запрос или запись файла и визуальная обработка выполняются только один раз.
В цикле for получите databasearray[0], сделайте запрос, запишите файл, обработайте его с помощью Vision API, обновите базу данных и перейдите к следующему элементу databasearray[1].
Я читал о Promises на разных страницах. Но я не понял.
Спасибо.
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var request = require('request');
var fs = require('fs');
//var fs = require("fs");
// Get a reference to the Cloud Vision API component
const Vision = require('@google-cloud/vision');
const vision = new Vision.ImageAnnotatorClient();
// Imports the Google Cloud client library
//const {Storage} = require('@google-cloud/storage');
var fs = require("fs");
var os = require("os");
var databaseArray = [];
exports.hourly_job = functions.pubsub
.topic('hourly-job')
.onPublish((event) => {
console.info("Hourly Job");
var db = admin.database();
var ref = db.ref("myData")
ref.once("value").then(function(allData) {
allData.forEach(function(deviceToken) {
deviceToken.forEach(function(firebaseIDs) {
var deviceTokenVar = deviceToken.key;
var firebaseIDVar = firebaseIDs.key;
var firstvalue = firebaseIDs.child("firstvalue").val();
var secondvalue = firebaseIDs.child("secondvalue").val();
var items = [deviceTokenVar, firebaseIDVar, firstvalue, secondvalue];
databaseArray.push([...items]);
});
});
return databaseArray;
}).then(function(databasem) {
var i;
for (i = 0; i < databaseArray.length; i++) {
var databaseArrayDeviceToken = databaseArray[i][0];
console.info("DeviceToken: " + databaseArrayDeviceToken);
var databaseArrayFirebaseID = databaseArray[i][1];
console.info("FirebaseID: " + databaseArrayFirebaseID);
var databaseArrayfirstvalue = databaseArray[i][2];
console.info("firstval: " + databaseArrayfirstvalue);
var databaseArraysecondval = databaseArray[i][3];
console.info("Second: " + databaseArraysecondval);
var url = "http://api.blabla" + databaseArrayfirstvalue;
/////////////here make a request, pause loop, process returned image, but how //////////////////////
request.get({
url: url,
encoding: 'binary'
}, function(error, httpResponse, body) {
if (!error && httpResponse.statusCode == 200) {
fs.writeFileSync('/tmp/processed.jpg', body, 'binary')
console.info("file written");
})
}
});
return true;
});
Пожалуйста, объясните свой ответ. Как я могу написать TypeScript? Я чисто новичок :)
следите за этой серией, очень полезно youtube.com/…
Я смотрю видео с вашим предложением. Но я не понял. Так жаль :(
Только что обнаружил, что js поддерживает async/await. пожалуйста, прочтите это blog.risingstack.com/mastering-async-await-in-nodejs
Сравните раздел «Решение 1: рождественская елка .then» с разделом «Благодаря использованию async/await наши проблемы волшебным образом исчезли».
Вау! Я получил решение с вашей помощью. Я публикую свое решение в разделе ответов. Но сейчас у меня другие проблемы. Цикл for ждет ответа с помощью await, но иногда он зависает на одном шаге. А иногда для функции цикла вызывается более одной. Я этого не понимаю. Я пишу их в разделе ответов. Еще раз спасибо.
Нет проблем, не стесняйтесь отметить мой комментарий как полезный, щелкнув треугольник вверх. Опубликуйте еще один вопрос с вашей проблемой
Я обновил свой ответ кодом. Взгляни, пожалуйста. Спасибо.





Я нашел решение с помощью Mocas. Вот решение. Я использую функции async/await в коде. Теперь цикл for ожидает ответа функции. Но сейчас у меня другие проблемы. Я думаю, что основная асинхронная функция зависает из-за ожидания. И затем следующий почасовой триггер снова запускается. Таким образом, журнал консоли показывает 15-16-17 или более значений «i» в цикле for. У меня есть 4 элемента в массиве базы данных, но журнал консоли показывает больше, чем каждый час. И с каждым разом увеличивается. Поэтому я предполагаю, что я должен отменить эти функции ожидания после тайм-аута. Но я не знаю как. Вот код:
use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var request = require('request-promise').defaults({ encoding: null });
var fs = require('fs');
// Get a reference to the Cloud Vision API component
const Vision = require('@google-cloud/vision');
const vision = new Vision.ImageAnnotatorClient();
var os = require("os");
var databaseArray = [];
var uniqueFilename = require('unique-filename')
exports.hourly_job = functions.pubsub
.topic('hourly-job')
.onPublish((event) => {
console.info("Hourly Job");
var db = admin.database();
var ref = db.ref("myData")
ref.once("value").then(function(allData) {
allData.forEach(function(deviceToken) {
deviceToken.forEach(function(firebaseIDs) {
var deviceTokenVar = deviceToken.key;
var firebaseIDVar = firebaseIDs.key;
var firstvalue = firebaseIDs.child("firstvalue").val();
var secondvalue = firebaseIDs.child("secondvalue").val();
var items = [deviceTokenVar, firebaseIDVar, firstvalue, secondvalue];
databaseArray.push([...items]);
//console.info(databaseArray);
//return true;
});
//return true;
});
return databaseArray;
}).then(function (databasem) {
main().catch(console.error);
});
return true;
});
const main = async () => {
var i;
for (i = 0; i < databaseArray.length; i++) {
console.info("Database Arrays " + i + ". elements: ");
var databaseArrayDeviceToken = databaseArray[i][0];
console.info("DeviceToken: " + databaseArrayDeviceToken);
var databaseArrayFirebaseID = databaseArray[i][1];
console.info("FirebaseID: " + databaseArrayFirebaseID);
var databaseArrayfirst = databaseArray[i][2];
console.info("first: " + databaseArrayfirst);
var databaseArraysecond = databaseArray[i][3];
console.info("second: " + databaseArraysecond);
if (databaseArrayfirst != "") {
var apiUrl = "http://api.blabla;
try {
const apiBody = await request.get(apiUrl);
///////////////////////////vison start//////////////////////
const visionResponseBody = await vision.documentTextDetection(apiBody)
var visionResponse = visionResponseBody[0].textAnnotations[0].description;
console.info("Vision response text " + visionResponse );
...some logic here about response...
/////////////////////////////////////////////////
var getdatabasevar = await admin.database().ref("myData/" + databaseArrayDeviceToken + "/" + databaseArrayFirebaseID);
await getdatabasevar.update({
"firstvalue": visionResponse
});
/////////////////////////////////////////////////
var getanotgerdatabasevar = await admin.database().ref("myData/" + databaseArrayDeviceToken + "/" + databaseArrayFirebaseID + "/" + "secondvalue");
await getanotgerdatabasevar.once("value")
.then(function(var) {
..some logic..
//send notification
});
} catch (error) {
console.error(error);
}
///////////////////////////vison end//////////////////////
}
};
return true;
};
Если бы это был я, я бы переключился на TypeScript и использовал Async/Await. Эти .then() действительно плохие