0

I am trying to properly execute some asynchronous calls. I basically have something that looks like this in order to getData1, then getData2, and finally userCheck:

for (const item of someArray) {
  this.getData1(item, userID).then(() =>
    this.getData2(item, userID).then(() =>
      this.userCheck(item)
    )
  );
}

and then inside getData1 and getData2 I subscribe to a GET request in a service I have created. I have one of the functions working properly because it is a just a simple Get request. I am having trouble with the other function. It is basically three GET request where the second call relies on the first and the third call relies on the second. I have incorporated promises and then statements to try and achieve this but it is still not working. The one I do not working I have tried several different things but have had no luck. My function currently looks like this.

getData2(user: string, id: string)
    {
        return new Promise((resolve, reject) =>
        {
            var status: string;

            this._apiService.getAssertion(id).toPromise().then((data: any) =>
            {
                let assert = data.toString();
                console.log(assert);
                this._apiService.getToken(assert, user).toPromise().then((data: any) =>
                {
                    let tkn = data.access_token.toString();
                    console.log(tkn);
                    this._apiService.ccMeta(tkn, guid).toPromise().then((information: any) =>
                    {
                        parseString(information, (err, result) =>
                        {
                            if (err)
                            {
                                throw new Error(err);
                            }
                            else
                            {
                                status = result['entry']
                                this.ccData.push(
                                {
                                    key: 'userStatus',
                                    value: status
                                })
                            }
                        });
                    });
                });
            }).then(() =>
                resolve()).then();
        })

  • You need to place the second http call inside the `then` callback where the first `response` is available. – Bergi Jun 11 '19 at 18:10
  • @Bergi can you review my edits please – new_programmer_22 Jun 19 '19 at 16:07
  • In the updated code, you need to avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it) and you probably are looking to [flatten your promise chain](https://stackoverflow.com/a/22000931/1048572). Don't forget to `return` values (or promises) from the `then` callbacks! – Bergi Jun 19 '19 at 16:38
  • @Bergi: Okay so I understand the flattening and antipattern now. So I am trying to propagate the results from the first ```_api.service``` call to the second one becuase the value returned from the first is needed in the second, but it turns out I am getting an error in the second call as if it is not propagating correctly. I'm not sure what is wrong because I am following the suggestions in [link](https://stackoverflow.com/questions/28714298/how-to-chain-and-share-prior-results-with-promises). – new_programmer_22 Jun 19 '19 at 18:20
  • In the code you posted, the result of the first request is needed as an argument to the second, but not in the callback of the second - the linked question (and [its duplicate](https://stackoverflow.com/q/28250680/1048572)) don't seem to apply here. All you need is a flat chain, similar to `apiService.getAssertion(id).then(assert => { return apiService.getToken(assert.toString(), user); }).then(data => { return apiService.ccMeta(data.access_token.toString(), guid); }).then(parseStringPromise).then(information => { this.ccData.push({key: 'userStatus', value: information.entry}); });` – Bergi Jun 19 '19 at 19:54
  • This still does not work as expected. For the second call to the service the results is returning as undefined. I know that I have assert before the call, but then when the second call is made, I would expect a get some data back but instead that data is undefined. @Bergi – new_programmer_22 Jun 20 '19 at 14:27
  • are you sure you didn't forget the `return`? If you have further problems, you might want to consider [asking a new question](https://stackoverflow.com/questions/ask) where you can post your current code – Bergi Jun 20 '19 at 14:38
  • I wanted to post a new clear question but stackoverflow says I have to wait so many days in between questions. Just to confirm, do you return the apiService call or do you return you value from like assert, data, information and then do the apiService call? I have tried both ways with still no luck – new_programmer_22 Jun 20 '19 at 14:51
  • I return the promise for the data that the apiService call did create. – Bergi Jun 20 '19 at 14:55

1 Answers1

-1

You can use some Rxjs to do it instead of using promises.

import { concatMap } from 'rxjs/operators';

this.http.post(someURL, httpOptions1).pipe(
   concatMap(res => {
      return this.http.get('second/req/url');
   }),
   concatMap(resFromSecondReq => {
      return this.http.get('third/req/url');
   })
).subscribe(resFromThirdReq => console.log('All requests successsful'));
AC101
  • 851
  • 8
  • 13
  • How would rxjs be an advantage over promises here? And this answer doesn't explain and solve the underlying problem in the code in the question. – Bergi Jun 11 '19 at 18:11
  • Why convert observables to promises to do something which can be done using observables with code that looks a lot more cleaner and still retains the potential to use more rxjs operators if needed. This example should do the same thing that you suggested in comment to original answer. – AC101 Jun 11 '19 at 18:22