0

So I have a complex question that may be easy to evaluate, but I am having issues getting it to work.

I have a global object that stores different form submissions and when a button is pressed it iterates through the values and his the APIs based on the key of the values inside. The function works, however the loop iterates completely and then the APIs are hit.

I want to splice or remove the values that are submitted successfully from the object and keep the ones that aren't. I also want to set some type of delay or timeout between each iteration to the API calls to I'm not hitting the API with each call all at one time.

My code may be more complex than it should be, but I've been trying to experiment with different sources. I also read about closures on the loops and understand why the loop is completing before the APIs are finishing, but I'm just wanting to know if there is a better way or basically wanting to get my code to function properly.

Any help on further educating me with this subject or alternative methods would be greatly appreciated.

Edit: So I removed the setTimeout() from the call and the iteration works as it should, but form some reason the array will splice up to the last two values and it gets stuck.I also noticed the i variable works as should when the API call is removed, but it gets thrown off when I add it.

My provider calling the API:

submitBatchData(data,authToken){
   //console.log(data,authToken);
   const httpOptions = {
       headers: new HttpHeaders({
           'Accept': 'application/json, text/plain',
           'Content-Type':  'application/json',
           'Authorization': authToken
            })
         };
      return this.http.post(this.apisubmitTreatUrl, JSON.stringify(data), httpOptions).retry(3).timeout(10000).delay(2000);

 }
The main while loop iteration:
  submitOfflineForm(data){
  var data = data;
  var length:number = data.length;
  var secondLength = data.length;
  var testLength = data.length;
  var count=0;

  while(secondLength--){//I have another loop that runs before checking for another value. Hance the multiple variables
    //console.log(secondLength);
    //console.log(count);
      this.callAPI(testLength,secondLength,data[secondLength],data);
  }
}
callAPI(testLength,i,data,allData) {
//where code is being run
}

When I run just the console logs and splicing array it works as should(3 Values in Array):

case "Batch": {
 console.log(i);
 console.log('Before: ' + allData);
 allData.splice(i,1);
 console.log('After: ' + allData);
break;
 }

Logs:

2
dataservice.ts:279 Before: [object Object],[object Object],[object Object]
dataservice.ts:281 After: [object Object],[object Object]
1
dataservice.ts:279 Before: [object Object],[object Object]
dataservice.ts:281 After: [object Object]
dataservice.ts:278
0
dataservice.ts:279 Before: [object Object]
dataservice.ts:281 After: 

But when I add the API call:

case "Batch": {
    // console.log("Here in Batch");
     submit.submitBatchData(data["Info"],token).subscribe((result)=>{
       //console.log(result["Status"]);
         if(result["Status"]==true){
            console.log(i);
            console.log('Before: ' + allData);
            allData.splice(i,1);
            console.log('After: ' + allData);
          // isEmpty(i,allData,storage,offline,loading);
         }
         else{
            this.presentToast('Batch Treatment not submitted with location!');
         }

     }, (err)=>{
        this.presentToast('Could not submit Batch Location!');
    });
    break;
 }    

Logs:

1
dataservice.ts:279 Before: [object Object],[object Object],[object Object]
dataservice.ts:281 After: [object Object],[object Object]
dataservice.ts:413 Current length of array after splicing: 2
dataservice.ts:414 (2) [{…}, {…}]
dataservice.ts:416 (2) [{…}, {…}]
2
dataservice.ts:279 Before: [object Object],[object Object]
dataservice.ts:281 After: [object Object],[object Object]
dataservice.ts:413 Current length of array after splicing: 2
dataservice.ts:414 (2) [{…}, {…}]
dataservice.ts:416 (2) [{…}, {…}]
0
dataservice.ts:279 Before: [object Object],[object Object]
dataservice.ts:281 After: [object Object]
dataservice.ts:413 Current length of array after splicing: 1
dataservice.ts:414 [{…}]
dataservice.ts:416 [{…}]

The value of i gets thrown off completely, I'm not sure why exactly that is happening. Any help would be appreciated.

Stephen Romero
  • 2,812
  • 4
  • 25
  • 48
  • Look into `promises` and `asynchronous wait (await)`, here are some documentation links (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) and (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) – Ryan Wilson Oct 26 '18 at 14:52
  • Would await work with observables? I am using observables for my API requests. – Stephen Romero Oct 26 '18 at 14:53
  • Looks like you can but only with the use of a promise, pleas see this SO post (https://stackoverflow.com/questions/34190375/how-can-i-await-on-an-rx-observable) – Ryan Wilson Oct 26 '18 at 14:54
  • Is there any way you could possibly provide an answer if I added more details on question? I have attempted to use the async, await on my observable callback but I'm not seeing any differences. Just the same results. – Stephen Romero Nov 03 '18 at 22:59

1 Answers1

1

I want to splice or remove the values that are submitted successfully from the object and keep the ones that aren't. I also want to set some type of delay or timeout between each iteration to the API calls to I'm not hitting the API with each call all at one time.

Is there a reason you need to splice and remove values? What if you keep the form item in the array and use a data structure that includes the state of the form?

[
    {
        form: {...},
        status: "pending" // or "invalid" or "submitted" etc
    },
    ...
]

If you follow this design you can iterate over the forms in different ways and multiple times without causing errors.

AJcodez
  • 31,780
  • 20
  • 84
  • 118
  • Well the issue with that is this feature is only utilized if the user cannot connect to my API(The users may potentially use the app where there is no connection). Hence saving the forms offline and re-submitting to the API when there is signal. Ideally it would make sense to remove the values from the array if they were submitted successfully and keep the ones in there if not. This allows the user to attempt multiple times until all are successful. Your method would work, however I feel like the structure would get really really big over time, unless there was something I could do to dump it. – Stephen Romero Nov 05 '18 at 15:37
  • After trying your solution approach I found that it actually worked! I was able to separate the submissions and array values and splice the values after the submissions were successfully hit! Thank you very much! – Stephen Romero Nov 05 '18 at 21:45