Executing Multiple Requests Concurrently in Angular 5 using forkJoin Technique


Important Note

The issue lies in the backend, not Angular. The requests are correct.


In my Angular5 app, I am trying to upload multiple files at once using rxjs forkJoin. I store the requests in an array as shown in the code below.

However, after adding the requests to the array, they all turn out to be the same request instead of uploading different selected files. Prior to adding them to the array, individual requests are correctly created by the service. I suspect this might be a pointer issue, and even tried creating a deep copy with Object.assign({}, request), but it did not work for the Observable.

Console log output (ignore the error, the server always rejects the second request due to a unique constraint requirement - this behavior is expected):

https://i.sstatic.net/mVHuI.png

Here's the component code:

uploadFiles() {
  var requests = [];
  var ctrNoFailuer = this.filesReplace.length;

  for (var i = 0; i < this.filesReplace.length; i++) {
    let request = this.solutionFileService.update(this.filesReplace[i][0], this.filesReplace[i][1]);
    console.log(request);
    requests.push(request);
  }

  if (requests.length == 0) {
    this.runTests();
  } else {
    forkJoin(requests).subscribe(
      res => {
        // [...]
      }
    )
  }
}

And here's how the service looks like:

update(solutionFile: SolutionFile, file?: File): Observable<SolutionFile> {
  console.log(solutionFile);
  let url = `${this.url}/src_uploads/${solutionFile.id}/`;

  if (file) {
    let headers = new HttpHeaders({
      'enctype': 'multipart/form-data',
      'Authorization': `JWT ${this.authService.getToken()}`
    })

    const formData: FormData = new FormData();
    formData.append('student_solution', String(solutionFile.student_solution));
    formData.append('file_src', file, file.name);

    return this.httpClient.put<SolutionFile>(url, formData, { headers: headers })
      .pipe(
        catchError(this.handleError('UPDATE solution-file', new SolutionFile()))
      );
  }

  return this.httpClient.put<SolutionFile>(url, solutionFile, { headers: this.headers })
    .pipe(
      catchError(this.handleError('UPDATE solution-file', new SolutionFile())
    )
  );
}

Answer №1

From what I can see, your code looks mostly correct. However, there are some areas where you could potentially make improvements, such as in factorisation and syntax. Here is an example of how you could enhance it:

uploadFiles() {
  const requests = this.filesReplace.map(fr => this.solutionFileService.update(fr[0], fr[1]));

  if (!requests.length) {
    this.runTests();
  } else {
    forkJoin(requests).subscribe(
      res => {
        // [...]
      }
    )
  }
}

update(solutionFile: SolutionFile, file ?: File): Observable < SolutionFile > {
  let url = `${this.url}/src_uploads/${solutionFile.id}/`;

  const headers = file ?
    new HttpHeaders({
      'enctype': 'multipart/form-data',
      'Authorization': `JWT ${this.authService.getToken()}`
    }) : this.headers;

  const formData: FormData = new FormData();
  formData.append('student_solution', String(solutionFile.student_solution));
  formData.append('file_src', file, file && file.name || undefined);

  const payload = file ? formData : solutionFile;

  return this.httpClient.put<SolutionFile>(url, payload, { headers })
    .pipe(
      catchError(() => this.handleError('UPDATE solution-file', new SolutionFile()))
    );
}

Furthermore, please consider sharing your logs in text format rather than through imgur links since not everyone may have access to that platform. Have you tried logging the result of the forkJoin call for debugging purposes?

Answer №2

Although I am not entirely clear on the question, it seems that forkJoin is not functioning as expected because you are attempting to pass an array of observables. To resolve this issue, consider using apply with an array of observables:

 forkJoin.apply(this, requests).subscribe(

I hope this suggestion proves helpful.

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

Begin a new project with Angular 4 by utilizing the Angular Command Line Interface

Can you guide me on starting a new project with the most recent release of Angular 4 using Angular CLI? The command to initiate this process is as follows: ng new new_project Here are the versions currently installed on my system: - @angular/cli: 1.0 ...

What is the best way to pass parameters in jQuery using .on()?

Hello there, I have a slight dilemma :) Could you please advise me on how to pass a parameter to an external JavaScript function using the .on method? Here is the code snippet: <script> var attachedPo = 0; $this.ready(function(){ $ ...

Ways to properly release file descriptors in write streams

I'm currently working on a code snippet that showcases what I'm aiming to achieve: const fs = require('fs'); var stream = fs.createWriteStream('/tmp/file'); stream.once('open', function(fd) { for (var i = 0; i ...

The clearInterval function in Javascript may not effectively halt an ongoing animation

Whenever I press a button, the element rotates using setInterval and clearInterval to stop rotation at a specific value by clearing the interval time t. Everything works perfectly except when I continually click the same button before the current animation ...

Is there a way to stop the Firebase web client from altering the error message generated by an https.onRequest function?

I am facing an issue where I cannot retrieve the original message I sent from an "https.onRequest" function in Firebase. The firebase client is rewriting the message based on the error code, making it difficult for me to recover the originally sent body or ...

Is it possible to make radio buttons in each row of a grid mutually exclusive within their respective column using JqGrid?

Is there a way to design a grid with a unique column of radio buttons so that when a user clicks on this column in a specific row, only the radio button in that row is selected? This column will contain a vertical group of radio buttons. I am seeking a so ...

Instead of loading the HTML into the div, Ajax is now sending me the link instead

I have just begun working on a new laravel project and am currently working on the user profile page, which will include a sidebar with links like Portfolio, Account Settings, etc. My goal is to dynamically load each page into a div when a link in the side ...

Implementing Angular routing within the Express framework can enhance the user experience

I'm diving into Angular and Node/Express for the first time. I've successfully set up a node/express server and loaded the main index.jade file. However, I'm struggling to use Angular for routing between links on this page. The console consi ...

Stop the infiltration of emotions into your style

Utilizing the JsonForms React Component to dynamically generate an HTML form in my web application. The framework I am using handles all view rendering on the server side. To integrate this component, I compiled a small react component by running npm run b ...

Angular does not seem to support drop and drag events in fullCalendar

I am looking to enhance my fullCalendar by adding a drag and drop feature for the events. This feature will allow users to easily move events within the calendar to different days and times. Below is the HTML code I currently have: <p-fullCalendar deep ...

Reset input fields upon jQuery removal

Currently, I am working on a form that includes a remove function. The function is functioning correctly, but I am facing an issue where I want the field values to be cleared when the remove function is triggered. This is necessary as I am sending input va ...

When using Angular 2's HTTP POST method, it initiates an OPTIONS request

I've come across a peculiar issue with my Angular 2 application. I'm trying to send a JSON via a POST call to my Play Scala API, but it keeps attempting to make an OPTIONS request. Below is the code snippet : LoginService constructor (private ...

Increase scrolling speed? - Background abruptly moves after scroll

I'm facing a minor issue. I want to create a parallax background effect similar to what can be seen on nikebetterworld.com. In my initial attempt, I managed to achieve some functionality, but I believe it can be improved. As I scroll, the background p ...

All authentication logic in Angular encapsulated within the service

I am considering moving all the business logic into the auth service and simply calling the method on the component side. Since none of my functions return anything, I wonder if it's okay or if they will hang. COMPONENT credentials: Credentials = ...

Ways to retrieve information from a $$state object

Everytime I try to access $scope.packgs, it shows as a $$state object instead of the array of objects that I'm expecting. When I console log the response, it displays the correct data. What am I doing wrong? This is my controller: routerApp.controll ...

Tips for getting information from firestore by implementing a where clause specific to a field within an object?

In my React Native project, I am utilizing Firebase Firestore as the backend database. I have successfully retrieved data from the database using the following code: unsubscribe = firebase.firestore().collection('messages').where('user&apos ...

The text field is being styled with inline styles automatically

I am trying to set a custom width for a textarea in my form, but the inline styles are automatically overriding my CSS. I have checked my scripts, but I am unsure which one is manipulating the DOM. If you have any insight, please let me know. This is the ...

Which costs more, using an undefined ng-bind or both ng-bind and ng-show together?

Assuming that toShowVar is undefined, which of these options would be more costly? <span ng-bind="toShowVar" ng-show="toShowVar"></span> or <span ng-bind="toShowVar"></span> The latter option would clearly not display anything o ...

Adjust the size of the wrapper/mask as the browser is resized

Is there a way to adjust the size of my wrapper and mask when the browser is resized? Currently, the mask stops once it's loaded, causing the content to be cut off when scrolling. You can view an example on this site. $(document).ready(function() { ...

Optimizing the particle rendering speed for HTML5 <canvas> elements

Currently conducting an experiment to enhance the maximum particle count before frame-rates begin to decrease in HTML5 Canvas. Utilizing requestAnimationFrame and employing drawImage from a canvas as it appears to be the most efficient method for image re ...