Ensure that Angular resolver holds off until all images are loaded

Is there a way to make the resolver wait for images from the API before displaying the page in Angular? Currently, it displays the page first and then attempts to retrieve the post images.

@Injectable()
export class DataResolverService implements Resolve<any> {
  constructor(
    private router: Router,
    private API: ApiService
  ) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<any> | Observable<never> {
    return this.API.getPostById(route.params.id).pipe(
      map(response => {
        if (response["images"]) {
          const images = [];
          response["images"].forEach(image => {
            this.API.getImageById(image.id).subscribe(
              (img: any) => {
                const imageObject = {
                  url: window.URL.createObjectURL(img),
                };
                images.push(imageObject);
              }
            );
          });
          response["images"] = images;
          return response;
        }

        return response;
      })
    );
  }
}

Answer №1

Give this a try:

@Injectable()
export class DataResolverService implements Resolve<any> {
  constructor(
    private router: Router,
    private API: ApiService
  ) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<any> | Observable<never> {
    return this.API.getPostById(route.params.id).pipe(
      switchMap(response => { // Try using switchMap here instead
        if (response["images"]) {
          return combineLatest(
            // Combine all image requests
            ...response["images"].map(image => this.API.getImageById(image.id)),
          ).pipe(
            map(images => images.map(image => ({ url: window.URL.createObjectURL(image) })),
            map(images => ({ response: images })), // This map might be unnecessary
          );
        } else {
         return of([]);
        }
      })
    );
  }
}

This should help you get started. The problem with your current approach is that you're subscribing to the inner observable and it may not be properly awaited by the route resolver.

Answer №2

Ensure that you are not returning "response" prematurely before the asynchronous method "this.API.getImageById(image.id)" has resolved. It is important to wait for all asynchronous iterations to complete before returning any data. There are several ways to achieve this, here is one approach:

return this.API.getPostById(route.params.id).pipe(
      map(async response => {
        if (response["images"]) {
          const images = [];
          response["images"].forEach(async image => {
           await this.API.getImageById(image.id).then(
              (img: any) => {
                const imageObject = {
                  url: window.URL.createObjectURL(img),
                };
                images.push(imageObject);
              }
            );
          });
          response["images"] = images;
          return response;
        }

        return response;
      })
    );

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for Repurposing a React Table

I am in the process of developing my own react component library to be used across my entire application. At the moment, I have started with a table component which is currently undergoing testing. However, I am facing the challenge of calling the componen ...

Troubleshooting AngularJS: Diagnosing Issues with My Watch Functionality

I need to set up a watch on a variable in order to trigger a rest service call whenever its value changes and update the count. Below is the code snippet I have: function myController($scope, $http) { $scope.abc = abcValueFromOutsideOfMyController; ...

Is there a method in TypeScript to create an extended type for the global window object using the typeof keyword?

Is it possible in TypeScript to define an extended type for a global object using the `typeof` keyword? Example 1: window.id = 1 interface window{ id: typeof window.id; } Example 2: Array.prototype.unique = function() { return [...new Set(this)] ...

Difficulty arises when Jest tests struggle to interpret basic HTML tags within a React Component

When running test runs, issues arise when using standard HTML tags with Jest. My setup includes Babel, Webpack, Jest, and React Testing Library. To enable jest, I have installed a number of packages: "@babel/plugin-proposal-class-properties": "7.8.3", "@ ...

What role does @next/react-dev-overlay serve in development processes?

Currently, I am diving into a NextJs project. Within the next.config.js file, there is this code snippet: const withTM = require('next-transpile-modules')([ 'some package', 'some package', 'emittery', ...

Modifying the HTML attribute value (of input) does not impact the value property

After inputting a single tag, I ran the following code in my Chrome console: https://i.stack.imgur.com/ySErA.jpg The result was unexpected for me. According to what I have read in a book, when I change an HTML attribute, the corresponding property should ...

Replace specific text with a span element around it?

I am working with the following HTML code: <p class="get">This is some content.</p>. My goal is to modify it so that it looks like this: <p class="get">This is <span>some</span> content.</p>. To achieve this, I have ...

Travis is checking to see if the undefined value is being

My experience with jasmine testing has been successful when done locally. However, I am encountering issues on Travis CI where all the API tests are returning undefined values. Here is an example: 4) Checking Server Status for GET /api/v1/orders - Expecte ...

Implementing a delay between two div elements using jQuery

I have two Divs with the class "sliced", each containing three images with the class "tile". When I animate using jQuery, I am unable to add a delay between the "sliced" classes. However, I have successfully added a delay between the "tile" classes. index ...

Is there an efficient method for transferring .env data to HTML without using templating when working with nodejs and expressjs?

How can I securely make an AJAX request in my html page to Node to retrieve process.env without using templating, considering the need for passwords and keys in the future? client-side // source.html $.get( "/env", function( data ) {console.log(data) ...

Consecutive pair of JavaScript date picker functions

My issue involves setting up a java script calendar date picker. Here are my input fields and related java scripts: <input type="text" class="text date" maxlength="12" name="customerServiceAccountForm:fromDateInput" id="customerServiceAccountForm:from ...

Ways to implement the tabIndex attribute in JSX

As per the guidelines provided in the react documentation, this code snippet is expected to function properly. <div tabIndex="0"></div> However, upon testing it myself, I encountered an issue where the input was not working as intended and ...

When running the command `npx create-react-app client`, an error is thrown stating "Reading properties of undefined is not possible (reading 'isServer')."

Installing packages. Please wait while the necessary packages are being installed. Currently installing react, react-dom, and react-scripts with cra-template... Encountered an error: Unable to read properties of undefined (reading 'isSer ...

Tips on fetching the ID of the selected option using JavaScript without relying on jQuery

Looking to print the selected option ID using pure Javascript (not JQuery) for multiple select tags. If we have more than one select tag, how do we achieve this? <select onchange="showOptions(this)" id="my_select1"> <option value="a1" id="ida ...

The operation failed because the property 'dasherize' is inaccessible on an undefined object

While attempting to execute the following command: ng generate component <component-name> An error occurred saying: Error: Cannot read property 'dasherize' of undefined Cannot read property 'dasherize' of undefined The confi ...

Expanding the padding of the selected item to create more breathing room

Upon examining the following: https://jsfiddle.net/h8kmove5/27/ Let's say you select 9 at the bottom. The display shows 8 9 10. My intention is to create some additional space on either side of 9, or any other active item for that matter. This way, ...

Error encountered during AJAX POST request: NETWORK_ERR code XMLHttpRequest Exception 101 was raised while using an Android device

Here is the ajax post code that I am using: $.ajax({ type: "POST", url: "http://sampleurl", data: { 'email':$('#email').val(), 'password':$('#password').val(), }, cache: false, ...

What methods are available for parsing JSON data into an array using JavaScript?

I possess an item. [Object { id=8, question="وصلت المنافذ الجمركية في...طنة حتّى عام 1970م إلى ", choice1="20 منفذًا", more...}, Object { id=22, question="تأسست مطبعة مزون التي تع... الأ ...

Retrieve an array from a JSON object by accessing the corresponding key/value pair using the utility library underscore

I have a dataset in JSON format (as shown below) and I am attempting to use the _.where method to extract specific values from within the dataset. JSON File "data": [{ "singles_ranking": [116], "matches_lost": ["90"], "singles_high_rank": [79 ...

Developing a react native library (create-react-native-library) incorporating a distinct react-native version within its designated Example directory

I'm looking to develop a React Native library, but the testing folder (example folder) it contains the latest version of React Native. However, I specifically need version 0.72.6 in the example folder. Is there a command for this? Current command: np ...