简体   繁体   中英

How to make two api calls using Promise.all within Angular9?

I making an api call using Promise.all as below:

    Promise.all(this.hostName.slice(0, this.Id.length).map((hostName) => {
        return this.serviceC.status(hostName)
            .then(res => {
                return new Promise((resolve, reject) => {
                    const oretry: ORInterface = {
                        oQid: res.rows[0].qid,
                        reason: this.reason
                    };
                    this.serviceB.retry(oretry).subscribe(resolve);
                });
            });
    }))
.then(() => {
        this.dialog.close();
    })
        .catch(err => {
            console.log(err);
        });

The above code is working fine. Now I want to make another api call after the successful completion of this.serviceB.retry(oretry) . The second api is this.serviceB.createDbEntry(sentry) and sentry looks as below:

                    const sretry: SDInterface = {
                        hostName,
                        Id: this.Id.slice(0, this.Id.length),
                        reason: this.reason
                    };

And, I am doing it as below

    Promise.all(this.hostName.slice(0, this.Id.length).map((hostName) => {
        return this.serviceC.status(hostName)
            .then(res => {
                return new Promise((resolve, reject) => {
                    const oretry: ORInterface = {
                        oQid: res.rows[0].qid,
                        reason: this.reason
                    };
                    const sretry: SDInterface = {
                        hostName,
                        Id: this.Id.slice(0, this.Id.length),
                        reason: this.reason
                    };
                    this.serviceB.retry(oretry).subscribe(resolve);
                    this.serviceB.createDbEntry(sentry).subscribe(resolve);
                });
            });
    }))
.then(() => {
        this.dialog.close();
    })
        .catch(err => {
            console.log(err);
        });

The above code is giving an error:

error: "SequelizeValidationError: string violation: Id cannot be an array or an object"

It is looks like it is not calling the second api for every Id

promise.all takes input in an array and gives response in an array,

Create 2 functions each with your asynchronous logic returning a promise,

Say funcA and funcB, then use below to invoke them parellely

Promise.all([funcA(this.hostName), funcB(this.id)])
    .then(respones => {
        console.log(responses[0]); //return value for funcA
        console.log(responses[1]); //return value for funcB
    })
    .catch(err => console.log(err));

I am assuming your logic of functions are correct, I just copy-pasted from your question and gave them structure

const funcA = (hostName) => {
hostName.slice(0, this.Id.length).map((hostName) => {
    return this.serviceC.status(hostName)
        .then(res => {
            return new Promise((resolve, reject) => {
                const oretry: ORInterface = {
                    oQid: res.rows[0].qid,
                    reason: this.reason
                };
                this.serviceB.retry(oretry).subscribe(resolve);
            });
        });
    });
}


const funcB = (Id) => {
Id.slice(0, this.Id.length).map(id => {
                return new Promise((resolve, reject) => {
                    const sretry: SDInterface = {
                        hostName,
                        Id: id,
                        reason: this.reason
                    };

                    this.serviceB.createDbEntry(sentry).subscribe(resolve);
                });
            })
}

You may want to take a look a forkJoin

import { Observable, forkJoin } from 'rxjs';

And then

ngOnInit() {
    let one = this.http.get('some/api/1') //some observable;
    let two = this.http.get('some/api/2') // another observable;

    forkJoin([one, tow]).subscribe(response => {
     // results[0] is our one call
     // results[1] is our second call
     let var1 = response[1];
     let var2 = response[0];
    }/*, error => { in case error handler } */); 
}

Wouldn't it be better to use Promise.all() once more?

Promise.all(this.hostName.slice(0, this.Id.length).map((hostName) => {
    return this.serviceC.status(hostName)
        .then(res => {
            return new Promise((resolve, reject) => {
                const oretry: ORInterface = {
                    oQid: res.rows[0].qid,
                    reason: this.reason
                };
                this.serviceB.retry(oretry).subscribe(resolve);
            });
        })
        .then(() => {
            return Promise.all(this.Id.slice(0, this.Id.length).map(id => {
                return new Promise((resolve, reject) => {
                    const sretry: SDInterface = {
                        hostName,
                        Id: id,
                        reason: this.reason
                    };

                    this.serviceB.createDbEntry(sentry).subscribe(resolve);
                });
            })
        });
}))
    .then(() => {
        this.dialog.close();
    })
    .catch(err => {
        console.log(err);
    });

And using toPromise() will make the code more concise.

Promise.all(this.hostName.slice(0, this.Id.length).map((hostName) => {
    return this.serviceC.status(hostName)
        .then(res => {
            const oretry: ORInterface = {
                oQid: res.rows[0].qid,
                reason: this.reason
            };
            return this.serviceB.retry(oretry).toPromise();
        })
        .then(() => {
            return Promise.all(this.Id.slice(0, this.Id.length).map(id => {
                const sretry: SDInterface = {
                    hostName,
                    Id: id,
                    reason: this.reason
                };

                this.serviceB.createDbEntry(sentry).toPromise();
            })
        });
}))
    .then(() => {
        this.dialog.close();
    })
    .catch(err => {
        console.log(err);
    });

Use combineLatest, in Angular we use RxJs not promises.

combineLatest(
  [this.http.get('call1'), this.http.get('call2')]
).subscribe(([result1, result2]) => {
  // do stuff with result1 and result2
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM