10

I have a problem where Angular2 makes the same request twice. I don't know why, though, because I have only one time a subscribe on the Observable. Here is my code:

My service looks like this:

getProjects(): Observable<Project[]> {
    return this.http.get(this.url)
        .map(this.mapProjects)
        .catch(this.handleError);
}

 private mapProjects(response: Response): any {
    const mappedProjects = response.json();
    return mappedProjects;
}

My component looks like this:

export class ProjectListComponent implements OnInit {

// List of projects
listProjects: Project[] = [];

constructor(private projectListService: ProjectListService) {
 }

public getProjectList() {
    this.projectListService.getProjects()
        .subscribe(
        projects => {
            this.listProjects = projects;
        },
        error => {
            // error handling
        });
}
}

In the network tab of the Chrome Developer Tools I see the request is made two times, once the initiator is zone.js, the other time it just says "Other". Can anyone explain this behaviour?

  • What you are describing seems like a preflight request made by the browser not angular. [please check this question](http://stackoverflow.com/questions/1256593/why-am-i-getting-an-options-request-instead-of-a-get-request). To verify that it is a preflight request, the method of the first request would be `OPTIONS`, the second would be a `GET` – Abdulrahman Alsoghayer Nov 23 '16 at 17:28
  • 1
    nice comment - is it 2 GET requests OR an OPTIONS request followed by a GET request, if the latter then abdul is correct, although im not sure GET requests do preflight requests?!* – danday74 Nov 23 '16 at 17:29
  • It is not an OPTIONS request, it is twice a GET request. – Boris Lapouchner Nov 23 '16 at 17:37
  • @BorisLapouchner please provide the code where you called `getProjectList()` , also, it would help to add a console log just in the beginning of `getProjectList()` to make sure the method itself is called only once. – Abdulrahman Alsoghayer Nov 23 '16 at 17:49
  • The first request was a OPTIONS request. Cause: I have a costom header 'Content-Type': 'application/json; charset=UTF-8', 'Accept': '*/*' – Boris Lapouchner Nov 24 '16 at 14:09

3 Answers3

9

I think that is preflight request. These are made before the actual request. Your preflight response needs to acknowledge these headers in order for the actual request to work.Once you send this response to the preflight request, the browser will make the actual request. https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests

Manish
  • 2,092
  • 16
  • 18
1

Without seeing the code I can only guess that your component is opened by the router, and you've configured a resolver that invokes getProjects(). In such case the resolver implicitly subscribes to the Observable returned by getProjects(). Hence you have a situation with two invocations of subscribe(): one explicit and one implicit.

Yakov Fain
  • 11,972
  • 5
  • 33
  • 38
0

not sure without seeing your entire codebase but this will fix it ...

.getProjects().first().subscribe(  ... etc

you will need to add

import 'rxjs/add/operator/first';

The first operator ensure subscribe is only called once. However, if you need it called multiple times (e.g. later on when an event occurs) then this will not be your solution.

PS subscribe is called every time the Observable stream emits. If the stream is emitting twice then subscribe is called twice. You can debug the Observable to see what it is emitting using do()

it would call it twice if ...

1 - you subscribe twice and it emits once, make sure you are not calling subscribe more than once

2 - it emits twice

danday74
  • 52,471
  • 49
  • 232
  • 283