Zachary Rich
Zachary Rich

Reputation: 41

setInterval is never firing in function and don't know why (angular)

I have this function which for some reason goes straight from printing 'submit component line after jobstart call' to 'entering while loop':

returned() {
    this.numReturned++;
    if (this.numReturned !== this.numSubmitting) {
        return;
    }
    console.log('submit component line before jobstart call');
    this.submitService.startJobToAuditTable().subscribe();
    console.log('submit component line after jobstart call');

    let timer = setInterval(() => {
        console.log('start of interval');
        this.submitService.checkIfJobRunning().subscribe(res => {
            console.log("res from job running check is " + res);
            this.jobFinished = res;
        });

        this.submitService.pollAuditTable().subscribe(res => {
            console.log("res from audit table:\n\t" + res);
            this.auditRows = res;
        });
    }, 10000);  //runs every 10 seconds. will be longer after testing

    console.log('entering while loop');
    while (this.jobFinished === false) {

    }

    console.log('clearing interval, job should be finished now');
    clearInterval(timer);
    return;
}

The console.log and other things inside of the setInterval never get called, and I am confused as to why that would be

Upvotes: 0

Views: 767

Answers (3)

Ski
Ski

Reputation: 14487

Your while loop is consuming execution and blocking everything. If you want to wait until job is done instead of while(done){} loop you can return a promise:

returned() {
  return new Promise((resolve, reject) => {
      this.numReturned++;
      if (this.numReturned !== this.numSubmitting) {
          resolve();
          return;
      }
      console.log('submit component line before jobstart call');
      this.submitService.startJobToAuditTable().subscribe();
      console.log('submit component line after jobstart call');

      let timer = setInterval(() => {

          console.log('start of interval');
          this.submitService.checkIfJobRunning().subscribe(res => {
              console.log("res from job running check is " + res);
              this.jobFinished = res;
          });

          this.submitService.pollAuditTable().subscribe(res => {
              console.log("res from audit table:\n\t" + res);
              this.auditRows = res;
          });

-->       if(this.jobFinished === false) {
              console.log('clearing interval, job should be finished now');
              clearInterval(timer);
              resolve();
          }

      }, 10000);  //runs every 10 seconds. will be longer after testing

  }
}

resolve() is used instead of return, in asynchronous code.

Later, when you call this function, if you want to wait until jobs are finished you can use await keyword

await returned ();  // will wait until resolve() is called
// code after all jobs done

or if async/await is not preferred:

returned().then(() => {
    // code after all jobs done
})

Upvotes: 1

Patrick Roberts
Patrick Roberts

Reputation: 51876

Well, if I understand what you're trying to do correctly, you can do something like this:

returned() {
    this.numReturned++;
    if (this.numReturned !== this.numSubmitting) {
        return resolve();
    }
    console.log('submit component line before jobstart call');
    this.submitService.startJobToAuditTable().subscribe();
    console.log('submit component line after jobstart call');

    let timer = setInterval(() => {
        console.log('start of interval');
        this.submitService.checkIfJobRunning().subscribe(res => {
            console.log("res from job running check is " + res);
            this.jobFinished = res;

            if (this.jobFinished) {
                console.log('clearing interval, job should be finished now');
                clearInterval(timer);
            }
        });

        this.submitService.pollAuditTable().subscribe(res => {
            console.log("res from audit table:\n\t" + res);
            this.auditRows = res;
        });
    }, 10000);  //runs every 10 seconds. will be longer after testing

    console.log('entering wait phase');
}

However, it seems you want the function to return when the job is finished, in which case you'll need to return a promise and declare its running scope as async:

returned() {
    return new Promise((resolve) => {
        this.numReturned++;
        if (this.numReturned !== this.numSubmitting) {
            return resolve();
        }
        console.log('submit component line before jobstart call');
        this.submitService.startJobToAuditTable().subscribe();
        console.log('submit component line after jobstart call');

        let timer = setInterval(() => {
            console.log('start of interval');
            this.submitService.checkIfJobRunning().subscribe(res => {
                console.log("res from job running check is " + res);
                this.jobFinished = res;

                if (this.jobFinished) {
                    console.log('clearing interval, job should be finished now');
                    clearInterval(timer);

                    resolve();
                }
            });

            this.submitService.pollAuditTable().subscribe(res => {
                console.log("res from audit table:\n\t" + res);
                this.auditRows = res;
            });
        }, 10000);  //runs every 10 seconds. will be longer after testing

        console.log('entering wait phase');
    })
}

And then how to call it:

async someOtherMemberMethod() {
    await this.returned();
    // job is finished here
}

or if you don't want to put it in an async function:

someOtherMemberMethod() {
    this.returned().then(() => {
        // job is finished here
    });
}

Upvotes: 0

theRemix
theRemix

Reputation: 2224

Remove this code, it's blocking, not allowing the process to trigger the next tick. So nothing else, including the setInterval will fire.

// Delete this
while (this.jobFinished === false) { }

Then you can move the clearInterval

this.submitService.checkIfJobRunning().subscribe(res => { 
  console.log("res from job running check is " + res); 
  this.jobFinished = res;
  if( this.jobFinished !== false ){
    clearInterval(timer);
  }
});

Upvotes: 0

Related Questions