ForEach только цикл по первому элементу в DataSnapshot - PullRequest
0 голосов
/ 03 апреля 2020

Я пытаюсь выполнить l oop через содержимое DataSnapshot, а затем в зависимости от условия выполнить некоторую работу для КАЖДОГО из элементов, но в настоящее время ForEach выполняет работу только с первым элементом. «ServerStatus» иногда ожидает, а иногда в «onCall». Когда первый элемент «onCall» не проникает через все остальные элементы, как я думаю, он должен go. Ниже снимок, откуда я получаю информацию:

enter image description here

И вот моя функция:

exports.manageCallRequests = functions.database.ref('/resquests/{userId}').onCreate((snap, context) => {
    const event = snap.val();

    console.log("function manageCallRequests is being called")
    var rootPath = admin.database().ref();
    var userOnCall = context.params.userId;

    var serversRef = rootPath.child('servers');
     var callRequest = event;
     var userTime = callRequest["time"];
     var waiting= "waiting";

  //We first get all the servers in ascending order depending on the last time they were used
  var serversSorted = serversRef.orderByChild('lastTimeUsed')


       //Gets the children on the "serversSorted" Query
       return serversSorted.once("value").then(allServers =>{
        //Checks if there is any child
            if(allServers.hasChildren()){



                    allServers.forEach(async function(server) {


                        //we extract the value from the server variable, this contains all the information 
                        //about each one of the servers we have
                        var serverInfo = server.val();
                        var serverKey = server.key;
                        var serverNumber = serverInfo["serverNumber"];
                        var serverStatus = serverInfo["serverStatus"];

console.log("server status "+serverStatus)
                        if(serverStatus === waiting){

                            const setCallRequest = await serversRef.child(serverKey).child("current").child("callRequest").set(callRequest);
                            const removeUserOnCall = await rootPath.child("resquests").child(userOnCall).remove();
                            const setServerStatus = await serversRef.child(serverKey).child("serverStatus").set("onCall");

                        }

                    });
                }else{
                    console.log("No servers available")


                }
            });

});

Ответы [ 2 ]

0 голосов
/ 04 апреля 2020

Я нашел 2 способа сделать это. Первый из них полезен, если у нас есть DataSnapshot без какого-либо вызова OrderBy *, в этом случае:

var allServers = await serversRef.once("value");

for (let serverKey of Object.keys(allServers.val())){
   var server = allServers[serverKey];
    //Do some work
}

Сначала нужно получить ключи объекта, чтобы затем можно было извлечь его из в пределах для l oop, как объяснено здесь в противном случае мы получим "Ошибка типа: 'x' не повторяется"

Теперь проблема в этом конкретном случае состоит в том, что DataSnapshot, который ранее был отсортирован в var serversSorted = serversRef.orderByChild('lastTimeUsed'), поэтому, когда мы вызываем Object.keys(allServers.val()), возвращаемое значение больше не сортируется, и здесь forEach () оказывается полезным. Это гарантирует, что потомки DataSnapshot будут повторяться в порядке их запросов, как объяснено здесь , однако по некоторым причинам при выполнении некоторой асинхронной c работы в forEach l oop это, похоже, не работает, это Вот почему я должен был сделать это:

var serversSorted = serversRef.orderByChild('lastTimeUsed')
    var allServers = await serversSorted.once("value");

    //Checks if there is any children
    if (allServers.hasChildren()) {
        //if there is iterate through the event that was passed in containing all
        // the servers
        var alreadyOnCall = false;
        var arrayOfServers = []
        var arrayOfKeys = []

        allServers.forEach(function(individualServer){
                arrayOfKeys.push(individualServer.key)
                arrayOfServers.push(individualServer)
        })

        for (var serveIndex = 0; serveIndex < arrayOfServers.length;serveIndex++){

            var serverObj = arrayOfServers[serveIndex]
            var serverObject = serverObj.val()
            var serverKey = arrayOfKeys[serveIndex]

            var serverStatus = serverObject["serverStatus"]; 
            var serverNumber = serverObject["serverNumber"]; 

            console.log("server info "+serverStatus+" "+serverKey);

            if (serverStatus === waiting && alreadyOnCall === false) {
                const setCallRequest = await serversRef.child(serverKey).child("current").child("callRequest").set(callRequest);
                const removeUserOnCall = await rootPath.child("resquests").child(userOnCall).remove();
                const setServerStatus = await serversRef.child(serverKey).child("serverStatus").set("onCall");
                alreadyOnCall= true
                console.log("Call properly set");
            } 
        }


    }
0 голосов
/ 03 апреля 2020

У меня было такое же поведение, потому что моя облачная функция была закрыта до того, как все итерации были выполнены в forEach l oop. Я избавился от этого, используя следующий фрагмент кода:

for (const doc of querySnapshot.docs) {
    // Do wathever you want    
    // for instance:
    await doc.ref.update(newData);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...