Enhanced API Requests: Leveraging Shared Observables
Written on
Chapter 1: Introduction to Declarative Programming
Declarative programming introduces exciting possibilities for addressing complex problems. Traditionally, when managing interconnected behaviors, developers often resort to increasing complexity with flags or similar constructs found in imperative programming. In this discussion, I will illustrate how to effectively handle sequential API requests through the use of RxJS and shared observables.
Use Case Overview
Our goal is to execute API requests in a specific order, where the response from the initial request is utilized to construct the payload for the subsequent one. Additionally, we wish to trigger certain logic immediately after the first request completes, regardless of the second request's outcome.
// Initiating the first request and sharing it to prevent multiple triggers
const firstRequest$ = from(fetch('...'))
.pipe(
mergeMap((response) => response.json()),
map((data) => ({firstRequest: data})),
share()
);
// Creating a dependent request that utilizes the shared observable
const secondRequest$ = firstRequest$
.pipe(
mergeMap((result) => {
const payload = result.data.map(item => item.email);
return fetch('...', {body: JSON.stringify(payload)});
}),
mergeMap((response) => response.json()),
map((data) => ({secondRequest: data}))
);
// Executing both requests concurrently
from([firstRequest$, secondRequest$])
.pipe(
// Aggregating responses
scan((accumulator, current) => {
return {...accumulator, ...current};}, {}),
// Confirming if the second request is completed
filter((response) => 'secondRequest' in response)
)
.subscribe({
next(response) {
// Process responses here},
error(error) {
// Handle errors from the requests
...
},
complete() {
// Finalize once all requests are complete}
});
In the code above, it is evident that we do not rely on any flags or state checks to ascertain if the first request has been completed before initiating the second request or executing additional logic.
Conclusion
Stream-oriented programming presents a transformative approach, providing us with robust tools for managing concurrent tasks seamlessly.