For loop an HTTP request logical error

#1

Hello,

Can anyone guide me on this? Below is the sample code. I tried to call an HTTP request inside the for loop, but the loop doesn’t wait for HTTP request finish already enter the next loop.

  • requestService.GetTelemetryData is the HTTP request.
GetGeneralInfo(){

for (let i = 0; i < deviceData.length; i++) {
conso.log("Loop Start")
            this.requestService.GetTelemetryData(loginAcc['token'], deviceData[i]["id"]["id"]).then((telemetryData) => {

              console.log("After GetTelemetryData()");
              let status = JSON.parse(telemetryData['status']);

              if (status == 401) {
                console.log("Token Expired...")

                this.requestService.RefreshToken(loginAcc['token'], loginAcc['refreshToken']).then(refreshTokenResponse => {

                 //i need to terminated the for loop and recall this method with new token
                  this.GetGeneralInfo();
                });

              }
              else if (status == 200) {
                console.log("Token is valid and data is given....")
                let data = JSON.parse(telemetryData['data']);
              }
            })
          }
}


The codes will continue for loop without waiting for the HTTP request finish. Let say the device data length is 2, for loop will print “Loop start” twice then only print "After GetTelemetryData()"

Currently

“Loop Start”
“Loop Start”
“After GetTelemetryData()”
“After GetTelemetryData()”

Expectation

“Loop Start”
“After GetTelemetryData()”
“Loop Start”
“After GetTelemetryData()”

Can guide me on this? Thanks.

#2

Hi @dmlkl :wave:

It’s a common async problem: all the calls made to this.requestService are asynchronous, but the loop keeps executing. In my experience, the cleanest way to make this async loop synchronous is by using async/await and waiting for the promises to resolve:

async function GetGeneralInfo() {
  for (let i = 0; i < deviceData.length; i++) {
    console.log('Loop Start')
    const telemetryData = await this.requestService.GetTelemetryData(loginAcc.token, deviceData[i].id.id);

    console.log('After GetTelemetryData()');
    const status = JSON.parse(telemetryData.status);

    if (status === 401) {
      console.log('Token Expired...');
      const refreshTokenResponse = await this.requestService.RefreshToken(loginAcc.token, loginAcc.refreshToken);

      //i need to terminated the for loop and recall this method with new token
      return this.GetGeneralInfo();
    } else if (status === 200) {
      console.log('Token is valid and data is given....');
      const data = JSON.parse(telemetryData.data);
    }
  }
}

Hope it helps,
Rodrigo

iOS Https GET POST issue return 0
#3

Hello,

I tried the function. It shows error “Unexpected token. A constructor, method, accessor, or property was expected.”. If I remove the “function” it shows “‘await’ expression is only allowed within an async function.ts”

Thanks.

#4

Hmm… That’s strange. What version of TypeScript is your project using (you can check it in package.json).

Also, can you paste the output of the ionic info command?

#5

Hello,

Thanks for reply. Below is the output after i run ionic info.

Ionic:

   ionic (Ionic CLI)  : 4.2.1 (C:\Users\King Lieng\AppData\Roaming\npm\node_modules\ionic)
   Ionic Framework    : ionic-angular 3.9.2
   @ionic/app-scripts : 3.2.1

Cordova:

   cordova (Cordova CLI) : 8.1.2 (cordova-lib@8.1.1)
   Cordova Platforms     : none
   Cordova Plugins       : not available

System:

   NodeJS : v10.15.1 (C:\Program Files\nodejs\node.exe)
   npm    : 6.4.1
   OS     : Windows 10


"typescript": "~2.6.2"

For tsconfig.json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": [
      "dom",
      "es2015"
    ],
    "module": "es2015",
    "moduleResolution": "node",
    "sourceMap": true,
    "target": "es5"
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules",
    "src/**/*.spec.ts",
    "src/**/__tests__/*.ts"
  ],
  "compileOnSave": false,
  "atom": {
    "rewriteTsconfig": false
  }
}

#6

Where does the GetGeneralInfo4() go? Is it a class method from a page component?
Does it work if you remove function and leave it as async GetGeneralInfo4()?

#7

Hello,

Finally, it works after I update the typescript version. But I not sure is because of the await function cause the delay on UI. When the data return from API (interval per 30 seconds), I push on the data to an array and display on HTML. When view on the UI, it causes flickering, seems like the data delay.

Thank you very much.