0

So, I've followed the answer from this question: Long Polling in Angular 4 but am still having problems.

The endpoint that I need to call and poll requires data from a call to another endpoint. So what I have is the following:

return this.postJob(ids)
    .flatMap(postRes => {
        return Observable
            .interval(250)
            .switchMap(() => { 
                console.log("POSTRES: " + JSON.stringify(postRes, null, 2); 
                return this.getJob(postRes.id);
            })
            .map(getRes => getRes)
            .takeWhile(getRes => {
                console.log("GETRES: " + JSON.stringify(getRes, null, 2); 
                return getRes.statusCode !== Constants.COMPLETE;
            })
            .catch(SharedHttpMethods.handleError);
    });

And I call that with:

processJob(ids).subscribe(jobRes => { 
    console.log("downloadSelected: ", JSON.stringify(jobRes, null, 2)); 
    // act on the completed response 
});

The problem I'm having is that the postJobs service is called over and over again. .takeWhile never kills the subscription. I am supposing that the flatMap may have something to do with that, but I am uncertain.

Any suggestions on what I need to do to fix this issue?

Notes: postJob and getJob returns the same json object model. However, getJob depends on the id returned from the postJobs call.

When I run my current code, I can see "QUEUED", "PROCESSING", and finally "COMPLETED". But they all happen multiple times.

Okay... it turns out I didn't look at my response closely enough.

** UPDATE with moderate successes ** Constants.COMPLETE = "COMPLETE"

The statusCode is giving me "COMPLETED".

Once I worked that out, getRes.statusCode !== Constants.COMPLETED, everything was working properly.

But I've run into a new problem. Once the .takeWhile gets a false statement, it stops the Observable. But it doesn't pass the final COMPLETED object back.

So, I get

GETRES: ... QUEUED
downloadSelected: ... QUEUED
GETRES: ... COMPLETED

but I do not get downloadSelected: ... COMPLETED. What am I missing

Output:

"POSTJOB":  {
  "_links": {
    "self": {
      "href": "http://localhost:9000/api/v1/jobs/44"
    }
  },
  "id": 44,
  "statusCode": "QUEUED",
}
"GETJOB":  {
 "_links": {
    "self": {
      "href": "http://localhost:9000/api/v1/jobs/44"
    }
  },
  "id": 44,
  "statusCode": "QUEUED",
}
"downloadSelected": {
  "_links": {
    "self": {
      "href": "http://localhost:9000/api/v1/jobs/44"
    }
  },
  "id": 44,
  "statusCode": "QUEUED",
}
"POSTJOB":  {
  "_links": {
    "self": {
      "href": "http://localhost:9000/api/v1/jobs/44"
    }
  },
  "id": 44,
  "statusCode": "QUEUED",
}
"GETJOB":  {
  "_links": {
    "self": {
      "href": "http://localhost:9000/api/v1/jobs/44"
    }
  },
  "id": 44,
  "statusCode": "PROCESSING",
}
"downloadSelected": {
  "_links": {
    "self": {
      "href": "http://localhost:9000/api/v1/jobs/44"
    }
  },
  "id": 44,
  "statusCode": "PROCESSING",
}
"POSTJOB":  {
  "_links": {
    "self": {
      "href": "http://localhost:9000/api/v1/jobs/44"
    }
  },
  "id": 44,
  "statusCode": "QUEUED",
}
"GETJOB":  {
  "_links": {
    "self": {
      "href": "http://localhost:9000/api/v1/jobs/44"
    },
    "zip": {
      "href": "linkToZipFile"
    }
  },
  "id": 44,
  "statusCode": "COMPLETED",
}
Machtyn
  • 2,982
  • 6
  • 38
  • 64
  • Is `flatMap` working as you want it to work? – Tadija Bagarić Nov 06 '17 at 18:37
  • As far as I can tell. I've got a couple of console loggers in the code I didn't repeat above and it shows me that both `postJob` and `getJob` calls are working and returning the correct data. The first response shows `{ id: 44, _links: { self: { href: "http://localhost:9000/api/v1/jobs/44" } }, statusCode: "QUEUED" }` and some moment later gives me: `{ id: 44, _links: { self: { href: "http://localhost:9000/api/v1/jobs/44" }, zip: { href: "linkToZipFile"} }, statusCode: "COMPLETED" }` – Machtyn Nov 06 '17 at 18:48
  • My guess is that your takeWhile is only completing the outer observable. Try also adding it to the inner observable within your switchMap `return this.getJob(postRes.id).takeWhile(...)` – LLai Nov 06 '17 at 20:39
  • After reading more about takeWhile, my above comment doesnt make sense :/ you said `.takeWhile never kills the subscription`. Do you mean you get 2 emits that are `COMPLETED`? or the observable sequence never stops and runs indefinitely? – LLai Nov 06 '17 at 21:03

1 Answers1

0

Okay... it turns out I didn't look at my response closely enough.

Constants.COMPLETE = "COMPLETE"

The statusCode is giving me "COMPLETED".

Once I worked that out, getRes.statusCode !== Constants.COMPLETED, everything was working properly.

For those who are looking for an answer on how to do multiple calls while utilizing .takeWhile, the answer is in the question. I needed the first object returned when statusCode==COMPLETED, but not anything beyond that first one. .takeWhile returns everything before COMPLETED. .skipWhile returns everything from the first COMPLETED and after. .take(1) limits the .skipWhile to just one call.

The answer I needed is the following. It utilizes .skipWhile and .take.

return this.postJob(ids)
    .flatMap(postRes => {
        return Observable
            .interval(250)
            .switchMap(() => { 
                console.log("POSTRES: " + JSON.stringify(postRes, null, 2); 
                return this.getJob(postRes.id);
            })
            .map(getRes => getRes)
            .skipWhile(getRes => {
                console.log("GETRES: " + JSON.stringify(getRes, null, 2); 
                return getRes.statusCode !== Constants.COMPLETE;
            })
            .take(1)
            .catch(SharedHttpMethods.handleError);
    });
Machtyn
  • 2,982
  • 6
  • 38
  • 64