Search code examples
javascriptarraysfor-loopxmlhttprequest

Javascript - How to pass array elements in batches of 99 to HTTP POST request and continue HTTP POST's until all array elements have been passed


I am attempting to pass 99 elements/values of an Array at a time to an XMLHttpRequest for a web app I am finishing up. The Array has more than 99 records, and will grow over time, as it pulling from user information in a database. My goal is to be able to send numerous HTTP POST requests containing 99 elements from that array at a time, OR until all elements of the array have been passed already. That is, 99 elements per batch and/ora final batch containing the last few remaining elements (less than 99) in the array. The method that I am using seems like it SHOULD work, but it is not currently working. Here is the code i am using:

      function sendPushNotification(allRecipients) {
        var listComplete = allRecipients.length;
        var batchMaker = 0;
        var batchRecipients;
        var batchNumber = 0;
        var recipientsProcessed = 0;
        for (batchMaker = 0; batchMaker < 99; batchMaker++) {
          batchRecipients =
            allRecipients[batchMaker] + `","` + batchRecipients;
          console.log(
            "Building Batch #" +
              batchNumber +
              1 +
              ":" +
              batchRecipients.slice(0, -11)
          );
          recipientsProcessed++;
          if (batchMaker == 99 || listComplete == recipientsProcessed) {
            console.log(batchRecipients.slice(0, -11));
            var subjectLineRaw = document.getElementById("subject").value;
            var messageBodyRaw = document.getElementById("body").value;
            const subjectLine = subjectLineRaw.replace(/(\r\n|\n|\r)/gm, " ");
            const messageBody = messageBodyRaw.replace(/(\r\n|\n|\r)/gm, " ");
            var data =
              `{
                "to": "` +
              JSON.stringify(batchRecipients.slice(0, -11)) +
              `",
                "title": "` +
              subjectLine +
              `",
                "body": "` +
              messageBody +
              `",
                "sound": "default"
              }`;
            console.log(data);

            var xhr = new XMLHttpRequest();
            var url =
              "url goes here";
            xhr.open("POST", url);
            xhr.setRequestHeader("accept", "application/json");
            xhr.setRequestHeader("content-type", "application/json");

            xhr.onreadystatechange = function () {
              if (xhr.readyState === 4) {
                console.log(xhr.status);
                console.log(xhr.responseText);
              }
            };
            // console.log(data);
            console.log(xhr);
            xhr.send(data);
            console.log(
              "Push Notification POST batch #" + ++batchNumber + "complete!"
            );
            batchMaker = 0;
          }
        }
      }

I can't seem to figure out why I am getting caught up, but my hunch is with regard to the criteria of the "for" and the "if" statements, that OR the reset of my counter "batchMaker" to be 0 at the end of my "if" statement.

When in debug mode, setting various breakpoints, as soon as batchMaker = 50, everything in my "if" statement does not get executed except resetting batchMaker = 0 again... which of course kills my loop. Setting the criteria in the "for" or "if" statement so that batchMaker is not the same for (batchMaker = 0; batchMaker < 99; batchMaker++) or if (batchMaker == 99 || listComplete == recipientsProcessed)... E.g. if both are not 99, I get an endless loop of console logs, and still never get a POST request executed... I feel like i am close, but maybe my method is flawed. I appreciate your help!


Solution

  • I was able to figure this out. Adding another "counter" mechanism batchCounter below, modifying the and if criteria to use this new batchCounterinstead of the same batchMaker, then resetting the value of this batchCounter variable so that for every subsequent loop/batch batchCounter and batchMaker interact the same as they did the very first loop (i.e. batchMaker == batchCounter +1 before meeting the 'if' statement criteria), and lastly breaking the loop entirely when recipientsProcessed begins to process 'undefined', that is a non-existence index number within my array which is displayed in the code as listComplete + 1 == recipientsProcessed. Here is the entire updated code snippet that is currently working as intended:

            var pageSelecterRadioButton = document.querySelector(
              'input[name="page_selecter"]:checked'
            );
            var pageSelected = pageSelecterRadioButton.value;
            var listComplete = allRecipients.length;
            var batchCounter = 0;
            var batchMaker = 0;
            var batchRecipients;
            var batchNumber = 0;
            var recipientsProcessed = 0;
            for (batchMaker = 0; batchMaker < 99; batchMaker++) {
              batchRecipients =
                allRecipients[recipientsProcessed] + `","` + batchRecipients;
              console.log(
                "Building Batch #" +
                  (batchNumber + 1) +
                  ':"' +
                  batchRecipients.slice(0, -11)
              );
              batchCounter++;
              recipientsProcessed++;
              if (batchCounter == 99 || listComplete == recipientsProcessed) {
                console.log(`"` + batchRecipients.slice(0, -11));
                var subjectLineRaw = document.getElementById("subject").value;
                var messageBodyRaw = document.getElementById("body").value;
                const subjectLine = subjectLineRaw.replace(/(\r\n|\n|\r)/gm, " ");
                const messageBody = messageBodyRaw.replace(/(\r\n|\n|\r)/gm, " ");
                var data =
                  `{
                    "to": ["` +
                  batchRecipients.slice(0, -11) +
                  `],
                    "title": "` +
                  subjectLine +
                  `",
                    "body": "` +
                  messageBody +
                  `",
                    "sound": "default",
                    "data": {"event": "` +
                  pageSelected +
                  `"}
                  }`;
                console.log(data);
    
                var xhr = new XMLHttpRequest();
                var url =
                  "https://stormy-peak-86652.herokuapp.com/https://exp.host/--/api/v2/push/send";
                xhr.open("POST", url);
                xhr.setRequestHeader("accept", "application/json");
                xhr.setRequestHeader("content-type", "application/json");
    
                xhr.onreadystatechange = function () {
                  if (xhr.readyState === 4) {
                    console.log(xhr.status);
                    console.log(xhr.responseText);
                  }
                };
                console.log(data);
                console.log(xhr);
                xhr.send(data);
                console.log(
                  "Push Notification POST batch #" + ++batchNumber + "complete!"
                );
                batchCounter = 2;
                batchMaker = 0;
                var batchRecipients = "         ";
              }
              if (listComplete + 1 == recipientsProcessed) {
                alert(recipientsProcessed - 1 + " Push Notifications Sent!");
                break;
              }
            }
          }
    

    There were some other additions made in the snippet above as well, but nothing that really involves the question here (added task to handle radio button value, and inputting that additional content in the HTTP Post, etc.). Hope this helps someone else someday!