后期操作不适用于Angular 4

时间:2022-11-23 17:55:43

I'm learning Node.JS with Angular 4. I build a sample Node API for simple GET/POST request. My GET operation works fine and I am able to fetch data in Angular. My OST operation isn't getting called at all from Angular. If I use Postman, I'm able to call POST successfully and data also gets inserted in database.

我正在使用Angular 4学习Node.JS。我为简单的GET / POST请求构建了一个示例Node API。我的GET操作工作正常,我能够在Angular中获取数据。我的OST操作根本没有从Angular调用。如果我使用Postman,我可以成功调用POST,数据也会插入数据库中。

Here is my sample code for Node POST:

这是我的Node POST示例代码:

app.post('/groups', function (req, res, next){


res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");
res.header("Access-Control-Allow-Methods", "GET, POST","PUT");

console.log('Request received with body' + req.body);
//DEV AWS MySQL
var mysql = require('mysql');

var connection = mysql.createConnection({
                      host     : 'xxxxxxx',
                      user     : 'xxxxxxx',
                      password : 'xxxxxxx',
                      database : 'xxxxxxx',
                      port     : 3306
});
connection.connect();

connection.query('CALL storedprocedure(?, ?, ?, ?, ?, ?)', [req.body.group_avatar_image,req.body.name,req.body.display_name,req.body.unique_id,req.body.description,req.body.adzone], function (err, results, fields){

    if (err)
        res.send(results);

    //res.status(201).send("Groups created successfully");
    res.status(201).send(results[0]);
});

This works fine with Postman and I get 201.

这对Po​​stman很好,我得到201。

Here is my Angular 4 code:

这是我的Angular 4代码:

    import { Injectable } from '@angular/core';
import { Http, Response,RequestOptions, Request, RequestMethod, Headers} from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import { Group } from './group';

@Injectable()
export class GroupsService{

    private _GroupsUrl = 'http://localhost:5000/api/groups';
    constructor(private _http: Http){};

    getGroups(): Observable<Group[]> {
        let headers = new Headers({ 'Content-Type': 'application/json' });
        headers.append('Accept', 'application/json');
        headers.append('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, DELETE, PUT');
        headers.append('Access-Control-Allow-Origin', '*');
        //headers.append('Access-Control-Allow-Headers', "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding");
        let options = new RequestOptions({ method: RequestMethod.Post, headers: headers,  url:this._GroupsUrl  });    

        //debugger;
        return this._http.get(this._GroupsUrl)
                .map((Response: Response) => <Group[]>Response.json()[0])
                //.do(data => console.log ('ALL: ' + JSON.stringify(data)))
                .catch(this.handleError);
    }

    CreateGroup(GroupM): Observable<string>{

        let headers = new Headers({ 'Content-Type': 'application/json' });
            headers.append('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, DELETE, PUT, OPTIONS');
            headers.append('Access-Control-Allow-Origin', 'http://localhost:4200');
            headers.append('Access-Control-Allow-Headers', "X-Requested-With, Content-Type");
        //let options = new RequestOptions({ method: RequestMethod.Post, headers: headers, body:JSON.stringify(GroupM),  url:this._GroupsUrl  });    
        let options = new RequestOptions({ method: RequestMethod.Post});    

        console.log('Calling ' + this._GroupsUrl + ' with body as :' + JSON.stringify(GroupM) + ' and request options are : ' + JSON.stringify(options));

        var req = new Request(options.merge({
        url: this._GroupsUrl
        }));

        debugger;
        //return this._http.post(this._GroupsUrl,GroupM)
        return this._http.post(req.url,JSON.stringify(GroupM),options)
                     .map(res => res.json())
                     .do(data => console.log ('ALL: ' + JSON.stringify(data)))
                     .catch(this.handleError);
    }

    private handleError(error:Response) {
        console.error(error);
        return Observable.throw(error.json().error || 'Server Error');
    }
}

What is wrong here?

这有什么不对?

3 个解决方案

#1


4  

Finally able to resolve it using promise and it resolves the issue. Not sure what exactly is the issue with observable.

最后能够使用promise解决它,它解决了这个问题。不确定observable究竟是什么问题。

>  CreateGroup(GroupObj:Group) : Promise<Group>{
        return this._http
                .post(this._GroupsUrl,JSON.stringify(GroupObj),{headers: this.headers})
                .toPromise()
                .then(res => res.json().data as Group)
                .catch(this.handleError);
    }

#2


2  

First of all, do yourself a favour and wrap Angular's Http service so that you don't have to manually add an auth token and headers for every request. Here's a simple implementation which you can build on:

首先,帮自己一个忙,并包装Angular的Http服务,这样你就不必为每个请求手动添加一个auth令牌和标题。这是一个可以构建的简单实现:

First of all let's create a Cookies service which will act as a fallback where localStorage isn't supported:

首先,让我们创建一个Cookies服务,它将作为不支持localStorage的后备:

@Injectable()

export class Cookies {

  public static getItem(sKey) {

    if (!sKey) {
      return null;
    }

    return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
  }

  public static setItem(sKey?, sValue?, vEnd?, sPath?, sDomain?, bSecure?) {

    if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) {
      return false;
    }

    let sExpires = '';

    if (vEnd) {

      switch (vEnd.constructor) {

        case Number:
          sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
          break;

        case String:
          sExpires = "; expires=" + vEnd;
          break;

        case Date:
          sExpires = "; expires=" + vEnd.toUTCString();
          break;
      }
    }

    document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");

    return true;
  }

  public static removeItem(sKey, sPath?, sDomain?) {

    if (!this.hasItem(sKey)) {
      return false;
    }

    document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");

    return true;
  }

  public static hasItem(sKey) {

    if (!sKey) {
      return false;
    }

    return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
  }

  public static keys() {

    let aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);

    for (let nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) {
      aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]);
    }

    return aKeys;
  }
}

Then a storage logger which keeps track of things added to the storage (useful for updating the auth token for every request when it changes):

然后是一个存储记录器,用于跟踪添加到存储中的内容(对于更改每个请求时更新身份验证令牌非常有用):

import {Cookies} from '@services/cookies.service';

@Injectable()

export class StorageLogger {

  private logger = new BehaviorSubject<any>(null);

  public logger$ = this.logger.asObservable();

  set(key: string, value: any): void {

    try {
      localStorage.setItem(key, JSON.stringify(value));
    }
    catch(err) {
      Cookies.setItem(key, JSON.stringify(value));
    }

    this.get(key);
  }

  get(key: string) {

    let item: any;

    try {
      item = JSON.parse(localStorage.getItem(key));
    }
    catch(err) {
      item = JSON.parse(Cookies.getItem(key));
    }

    this.logger.next({value: item, key: key});
  }

  remove(keys: string[]) {

    try {

      for (const key of keys) {
        localStorage.removeItem(key);
        this.logger.next({value: null, key: key});
      }
    }
    catch(err) {

      for (const key of keys) {
        Cookies.removeItem(key);
        this.logger.next({value: null, key: key});
      }
    }
  }
}

Then you want to wrap angular's Http:

然后你想包装angular的Http:

@Injectable()

/* Wrapper for Angular's Http class, let's us provide headers and other things on every request */
export class HttpClient implements OnDestroy {

  constructor(
    private http: Http,
    private storageLogger: StorageLogger
  ) {

    this.getToken();

    this.storageSubscription = this.storageLogger.logger$.subscribe(
      (action: any) => {

        if (action && action.key === tokenIdKey) {
          this.getToken();
        }
      }
    );
  }

  private storageSubscription: Subscription;
  private token: string;

  ngOnDestroy() {
    this.storageSubscription.unsubscribe();
  }

  getToken(): void {

    try {
      this.token = localStorage.getItem(tokenIdKey);
    }
    catch(error) {
      this.token = Cookies.getItem(tokenIdKey);
    }
  }

  convertJSONtoParams(json: any): URLSearchParams {

    const params: URLSearchParams = new URLSearchParams();

    for (const key in json) {

      if (json.hasOwnProperty(key) && json[key]) {

        if (json[key].constructor === Array && !json[key].length) {
          continue;
        }
        else {
          params.set(key, json[key]);
        }
      }
    }

    return params;
  }

  getRequestOptions(params?: any): RequestOptions {

    const headers = new Headers();

    // headers.append('Content-Type', 'application/x-www-form-urlencoded');
    headers.append('Content-Type', 'application/json');

    this.createAuthorizationHeader(headers);

    return new RequestOptions({
      headers: headers,
      search: params ? this.convertJSONtoParams(params) : null
    });
  }

  createAuthorizationHeader(headers: Headers): void {
    headers.append('Authorization', this.token);
  }

  checkResponseStatus(err: any) {

    if (err.status === 401) {

      // If we want we can redirect to login here or something else
    }

    return Observable.of(err);
  }

  get(url: string, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.get(host + url, options).catch((err: Response) => this.checkResponseStatus(err));
  }

  post(url: string, data: any, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.post(host + url, data, options).catch((err: Response) => this.checkResponseStatus(err));
  }

  put(url: string, data: any, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.put(host + url, data, options).catch((err: Response) => this.checkResponseStatus(err));
  }

  delete(url: string, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.delete(host + url, options).catch((err: Response) => this.checkResponseStatus(err));
  }

  patch(url: string, data: any, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.patch(host + url, data, options).catch((err: Response) => this.checkResponseStatus(err));
  }

  head(url: string, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.head(host + url, options).catch((err) => this.checkResponseStatus(err));
  }

  options(url: string, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.options(host + url, options).catch((err: Response) => this.checkResponseStatus(err));
  }
}

And finally you should also add a generic api service which you will call, instead of creating a new service for every part of your application. This will save you a lot of code and effort. Here it is:

最后,您还应该添加一个通用的api服务,而不是为应用程序的每个部分创建新服务。这将为您节省大量代码和工作量。这里是:

import {IResponse} from '@interfaces/http/response.interface';
import {HttpClient} from '@services/http/http-client.service';

@Injectable()

export class AppApi {

  constructor(private http: HttpClient) {}

  get(url: string, params?: any): Observable<IResponse> {

    return this.http.get(url, params)
      .map((res: Response) => res.json() as IResponse)
      .catch((error: any) => {
        return Observable.throw(error.json().error || 'Server error');
      }
    );
  }

  post(url: string, data: any, params?: any) {

    return this.http.post(url, data, params)
      .map((res: Response) => res.json() as IResponse)
      .catch((error: any) => {
        return Observable.throw(error.json().error || 'Server error');
      }
    );
  }

  put(url: string, data: any, params?: any) {

    return this.http.put(url, data, params)
      .map((res: Response) => res.json() as IResponse)
      .catch((error: any) => {
        return Observable.throw(error.json().error || 'Server error');
      }
    );
  }

  delete(url: string, params?: any): Observable<IResponse> {

    return this.http.delete(url, params)
      .map((res: Response) => res.json() as IResponse)
      .catch((error: any) => {
        return Observable.throw(error.json().error || 'Server error');
      }
    );
  }
}

You'll notice that I've also created an interface which types up my response from the backend, which is usually something like:

您会注意到我还创建了一个界面,它从后端输入我的响应,通常类似于:

{error: any; data: any; results: number; total: number;}

Now that we've taken care of those problems, let's tackle your original question. The most likely reason as to why your request isn't running, is that you're not subscribing to the http observable. Observables are lazy so if you don't subscribe to it via .subscribe or @ngrx/effects, it just won't do anything.

现在我们已经解决了这些问题,让我们解决你原来的问题。您的请求未运行的最可能原因是您没有订阅http observable。 Observable是懒惰的,所以如果你不通过.subscribe或@ngrx / effects订阅它,它就不会做任何事情。

So let's assume that you're calling CreateGroup like this:

所以我们假设您正在调用CreateGroup,如下所示:

this.groupsService.CreateGroup(data);

This won't do anything until you subscribe:

在您订阅之前,这不会做任何事情:

this.groupsService.CreateGroup(data).subscribe(() => {

  // Here you can react to the post, close a modal, redirect or whatever you want.
});

I'd also recommend adding a .first() to your api calls as this will prevent you from having to unsubscribe from the observables manually when the component is destroyed.

我还建议在api调用中添加.first(),因为这样可以防止在组件被销毁时手动取消订阅observable。

So to use the implementation as above you'd simply do:

因此,要使用上面的实现,您只需执行以下操作:

constructor(private appApi: AppApi) {}

...

this.appApi.post('/groups').first().subscribe(() => {

  // Do something
});

I hope this is helpful.

我希望这是有帮助的。

#3


0  

Don't stringify the POST data in HTTP POST. Simply pass the object.

不要在HTTP POST中对POST数据进行字符串化。简单地传递对象。

#1


4  

Finally able to resolve it using promise and it resolves the issue. Not sure what exactly is the issue with observable.

最后能够使用promise解决它,它解决了这个问题。不确定observable究竟是什么问题。

>  CreateGroup(GroupObj:Group) : Promise<Group>{
        return this._http
                .post(this._GroupsUrl,JSON.stringify(GroupObj),{headers: this.headers})
                .toPromise()
                .then(res => res.json().data as Group)
                .catch(this.handleError);
    }

#2


2  

First of all, do yourself a favour and wrap Angular's Http service so that you don't have to manually add an auth token and headers for every request. Here's a simple implementation which you can build on:

首先,帮自己一个忙,并包装Angular的Http服务,这样你就不必为每个请求手动添加一个auth令牌和标题。这是一个可以构建的简单实现:

First of all let's create a Cookies service which will act as a fallback where localStorage isn't supported:

首先,让我们创建一个Cookies服务,它将作为不支持localStorage的后备:

@Injectable()

export class Cookies {

  public static getItem(sKey) {

    if (!sKey) {
      return null;
    }

    return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
  }

  public static setItem(sKey?, sValue?, vEnd?, sPath?, sDomain?, bSecure?) {

    if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) {
      return false;
    }

    let sExpires = '';

    if (vEnd) {

      switch (vEnd.constructor) {

        case Number:
          sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
          break;

        case String:
          sExpires = "; expires=" + vEnd;
          break;

        case Date:
          sExpires = "; expires=" + vEnd.toUTCString();
          break;
      }
    }

    document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");

    return true;
  }

  public static removeItem(sKey, sPath?, sDomain?) {

    if (!this.hasItem(sKey)) {
      return false;
    }

    document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");

    return true;
  }

  public static hasItem(sKey) {

    if (!sKey) {
      return false;
    }

    return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
  }

  public static keys() {

    let aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);

    for (let nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) {
      aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]);
    }

    return aKeys;
  }
}

Then a storage logger which keeps track of things added to the storage (useful for updating the auth token for every request when it changes):

然后是一个存储记录器,用于跟踪添加到存储中的内容(对于更改每个请求时更新身份验证令牌非常有用):

import {Cookies} from '@services/cookies.service';

@Injectable()

export class StorageLogger {

  private logger = new BehaviorSubject<any>(null);

  public logger$ = this.logger.asObservable();

  set(key: string, value: any): void {

    try {
      localStorage.setItem(key, JSON.stringify(value));
    }
    catch(err) {
      Cookies.setItem(key, JSON.stringify(value));
    }

    this.get(key);
  }

  get(key: string) {

    let item: any;

    try {
      item = JSON.parse(localStorage.getItem(key));
    }
    catch(err) {
      item = JSON.parse(Cookies.getItem(key));
    }

    this.logger.next({value: item, key: key});
  }

  remove(keys: string[]) {

    try {

      for (const key of keys) {
        localStorage.removeItem(key);
        this.logger.next({value: null, key: key});
      }
    }
    catch(err) {

      for (const key of keys) {
        Cookies.removeItem(key);
        this.logger.next({value: null, key: key});
      }
    }
  }
}

Then you want to wrap angular's Http:

然后你想包装angular的Http:

@Injectable()

/* Wrapper for Angular's Http class, let's us provide headers and other things on every request */
export class HttpClient implements OnDestroy {

  constructor(
    private http: Http,
    private storageLogger: StorageLogger
  ) {

    this.getToken();

    this.storageSubscription = this.storageLogger.logger$.subscribe(
      (action: any) => {

        if (action && action.key === tokenIdKey) {
          this.getToken();
        }
      }
    );
  }

  private storageSubscription: Subscription;
  private token: string;

  ngOnDestroy() {
    this.storageSubscription.unsubscribe();
  }

  getToken(): void {

    try {
      this.token = localStorage.getItem(tokenIdKey);
    }
    catch(error) {
      this.token = Cookies.getItem(tokenIdKey);
    }
  }

  convertJSONtoParams(json: any): URLSearchParams {

    const params: URLSearchParams = new URLSearchParams();

    for (const key in json) {

      if (json.hasOwnProperty(key) && json[key]) {

        if (json[key].constructor === Array && !json[key].length) {
          continue;
        }
        else {
          params.set(key, json[key]);
        }
      }
    }

    return params;
  }

  getRequestOptions(params?: any): RequestOptions {

    const headers = new Headers();

    // headers.append('Content-Type', 'application/x-www-form-urlencoded');
    headers.append('Content-Type', 'application/json');

    this.createAuthorizationHeader(headers);

    return new RequestOptions({
      headers: headers,
      search: params ? this.convertJSONtoParams(params) : null
    });
  }

  createAuthorizationHeader(headers: Headers): void {
    headers.append('Authorization', this.token);
  }

  checkResponseStatus(err: any) {

    if (err.status === 401) {

      // If we want we can redirect to login here or something else
    }

    return Observable.of(err);
  }

  get(url: string, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.get(host + url, options).catch((err: Response) => this.checkResponseStatus(err));
  }

  post(url: string, data: any, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.post(host + url, data, options).catch((err: Response) => this.checkResponseStatus(err));
  }

  put(url: string, data: any, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.put(host + url, data, options).catch((err: Response) => this.checkResponseStatus(err));
  }

  delete(url: string, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.delete(host + url, options).catch((err: Response) => this.checkResponseStatus(err));
  }

  patch(url: string, data: any, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.patch(host + url, data, options).catch((err: Response) => this.checkResponseStatus(err));
  }

  head(url: string, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.head(host + url, options).catch((err) => this.checkResponseStatus(err));
  }

  options(url: string, params?: any): Observable<Response> {

    const options: RequestOptions = this.getRequestOptions(params);

    return this.http.options(host + url, options).catch((err: Response) => this.checkResponseStatus(err));
  }
}

And finally you should also add a generic api service which you will call, instead of creating a new service for every part of your application. This will save you a lot of code and effort. Here it is:

最后,您还应该添加一个通用的api服务,而不是为应用程序的每个部分创建新服务。这将为您节省大量代码和工作量。这里是:

import {IResponse} from '@interfaces/http/response.interface';
import {HttpClient} from '@services/http/http-client.service';

@Injectable()

export class AppApi {

  constructor(private http: HttpClient) {}

  get(url: string, params?: any): Observable<IResponse> {

    return this.http.get(url, params)
      .map((res: Response) => res.json() as IResponse)
      .catch((error: any) => {
        return Observable.throw(error.json().error || 'Server error');
      }
    );
  }

  post(url: string, data: any, params?: any) {

    return this.http.post(url, data, params)
      .map((res: Response) => res.json() as IResponse)
      .catch((error: any) => {
        return Observable.throw(error.json().error || 'Server error');
      }
    );
  }

  put(url: string, data: any, params?: any) {

    return this.http.put(url, data, params)
      .map((res: Response) => res.json() as IResponse)
      .catch((error: any) => {
        return Observable.throw(error.json().error || 'Server error');
      }
    );
  }

  delete(url: string, params?: any): Observable<IResponse> {

    return this.http.delete(url, params)
      .map((res: Response) => res.json() as IResponse)
      .catch((error: any) => {
        return Observable.throw(error.json().error || 'Server error');
      }
    );
  }
}

You'll notice that I've also created an interface which types up my response from the backend, which is usually something like:

您会注意到我还创建了一个界面,它从后端输入我的响应,通常类似于:

{error: any; data: any; results: number; total: number;}

Now that we've taken care of those problems, let's tackle your original question. The most likely reason as to why your request isn't running, is that you're not subscribing to the http observable. Observables are lazy so if you don't subscribe to it via .subscribe or @ngrx/effects, it just won't do anything.

现在我们已经解决了这些问题,让我们解决你原来的问题。您的请求未运行的最可能原因是您没有订阅http observable。 Observable是懒惰的,所以如果你不通过.subscribe或@ngrx / effects订阅它,它就不会做任何事情。

So let's assume that you're calling CreateGroup like this:

所以我们假设您正在调用CreateGroup,如下所示:

this.groupsService.CreateGroup(data);

This won't do anything until you subscribe:

在您订阅之前,这不会做任何事情:

this.groupsService.CreateGroup(data).subscribe(() => {

  // Here you can react to the post, close a modal, redirect or whatever you want.
});

I'd also recommend adding a .first() to your api calls as this will prevent you from having to unsubscribe from the observables manually when the component is destroyed.

我还建议在api调用中添加.first(),因为这样可以防止在组件被销毁时手动取消订阅observable。

So to use the implementation as above you'd simply do:

因此,要使用上面的实现,您只需执行以下操作:

constructor(private appApi: AppApi) {}

...

this.appApi.post('/groups').first().subscribe(() => {

  // Do something
});

I hope this is helpful.

我希望这是有帮助的。

#3


0  

Don't stringify the POST data in HTTP POST. Simply pass the object.

不要在HTTP POST中对POST数据进行字符串化。简单地传递对象。