Angular2 http.post gets executed twice

2019-01-11 06:20发布

问题:

I came across a weird issue where the Angular2's (RC1) Http service executes the http.post call twice. I've debugged my app and I know for a fact this is not a click event issue. All the calls that lead up to the core service call

public create(json: Object, params?: Object): Observable<T> {
    let body = JSON.stringify([json]);
    let headers = this.getHeaders();
    let options = new RequestOptions({ headers: headers });

    return this._http.post(this.createURL(this.getCreateURL(), [], params), body, options)
    .map(res => this.handleObjectResponse(res));
}

are run once. Then when I started tracing the issue I found out that my handler this.handleObjectResponse gets executed twice. So I delved further and reached @angular/http/src/backends/xhr_backend.ts where they do this

constructor(req: Request, browserXHR: BrowserXhr, baseResponseOptions?: ResponseOptions) {
    this.request = req;
    this.response = new Observable<Response>((responseObserver: Observer<Response>) => {
        let _xhr: XMLHttpRequest = browserXHR.build();
        _xhr.open(RequestMethod[req.method].toUpperCase(), req.url);
        // load event handler
        ...
        ..

So I put a breakpoint on this.request = req; and then another breakpoint on let _xhr: XMLHttpRequest = browserXHR.build(); and I found out I hit the first breakpoint once but then I hit the second breakpoint from the callback twice.

This has been driving me nuts so I wanted to check whether anyone familiar with the angular2 internals could shed some light whether this looks like a bug or something that I've done wrong.

In my code I've created some abstract generic service classes: GenericService and FullService which extends GenericService. Both of these are abstract and use generics and the real service classes that get injected in the different components all extend either GenericService or FullService. Do you guys think this setup could possibly be responsible for the double post executions?

All ideas are appreciated!

Thanks in advance!

P.S.

This doesn't happen with gets but it also happens with puts.

回答1:

The http service returns a cold observable that get executed on every subscribe, you want to convert it to a hot observable that get only executed on the first subscribe and share the same value for subsequent subscribes.

To convert it all you have to do is share it:

return this._http.post(this.createURL(this.getCreateURL(), [], params), body, options)
.map(res => this.handleObjectResponse(res))
.share();


回答2:

This was happening to me because I have (key.enter)="someSubmitFunction()" on one of the input fields of a form. When I hit enter on this field the form would submit twice. Apparently, this wasn't needed. When I removed this, the form would still submit when I hit enter, but now only once.



回答3:

its happening because HTTP OPTIONS executed first, and you have to restrict unwanted HTTP method before executing your Logic, always use isset method,see example below

 if(isset($_POST))
 {
    $name = $_POST["name"];
    $country = $_POST["country"];

    $sql = 'INSERT INTO user values("' . $name . '","' . $country . '")';

            if ( $conn->query($sql)=== TRUE) 
            {
                $outp =  "Inserted " .  $name . "  and  "  . $country;
                echo json_encode($outp);
            } else {
                echo json_encode("Error: " . $sql . "<br>" . $conn->error);
            }
        }


here it will insert row in table only when its POST METHOD.