Node.js 操作后不使用角度4

Node.js 操作后不使用角度4,node.js,angular,Node.js,Angular,我正在用Angular 4学习Node.JS。我为简单的GET/POST请求构建了一个示例节点API。我的GET操作运行良好,我能够以角度方式获取数据。我的OST操作根本没有被Angular调用。若我使用Postman,我就能够成功地呼叫POST,并且数据也会被插入到数据库中 以下是我的节点帖子示例代码: app.post('/groups', function (req, res, next){ res.header("Access-Control-Allow-Origin", "*");

我正在用Angular 4学习Node.JS。我为简单的GET/POST请求构建了一个示例节点API。我的GET操作运行良好,我能够以角度方式获取数据。我的OST操作根本没有被Angular调用。若我使用Postman,我就能够成功地呼叫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]);
});
这对邮递员很有效,我得到201

这是我的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');
    }
}
从'@angular/core'导入{Injectable};
从'@angular/Http'导入{Http,Response,RequestOptions,Request,RequestMethod,Headers};
从“rxjs/Observable”导入{Observable};
导入'rxjs/add/operator/map';
导入“rxjs/add/operator/catch”;
导入'rxjs/add/operator/do';
从“./Group”导入{Group};
@可注射()
导出类组服务{
私人团体http://localhost:5000/api/groups';
构造函数(私有http:http){};
getGroups():可观察{
let 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-request-With,内容类型,来源,授权,接受,客户端安全令牌,接受编码”);
let options=new RequestOptions({method:RequestMethod.Post,headers:headers,url:this.\u GroupsUrl});
//调试器;
返回此。_http.get(此。_GroupsUrl)
.map((Response:Response)=>Response.json()[0])
//.do(data=>console.log('ALL:'+JSON.stringify(data)))
.接住(这个.把手错误);
}
CreateGroup(GroupM):可观察{
let 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-request-With,Content-Type');
//let options=new RequestOptions({method:RequestMethod.Post,headers:headers,body:JSON.stringify(GroupM),url:this.\u GroupsUrl});
let options=newrequestoptions({method:RequestMethod.Post});
log('Calling'+this._GroupsUrl++',主体为:'+JSON.stringify(GroupM)+',请求选项为:'+JSON.stringify(options));
var req=新请求(options.merge({
url:this.\u GroupsUrl
}));
调试器;
//返回此。_http.post(此。_GroupsUrl,GroupM)
返回此信息。_http.post(req.url、JSON.stringify(GroupM)、options)
.map(res=>res.json())
.do(data=>console.log('ALL:'+JSON.stringify(data)))
.接住(这个.把手错误);
}
私有句柄错误(错误:响应){
控制台错误(error);
返回Observable.throw(error.json().error | |'Server error');
}
}

这里出了什么问题?

首先,帮自己一个忙,包装Angular的
Http
服务,这样您就不必为每个请求手动添加身份验证令牌和头。下面是一个简单的实现,您可以在此基础上进行构建:

首先,让我们创建一个
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;
  }
}
最后,您还应该添加一个您将调用的通用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');
      }
    );
  }
}
现在我们已经解决了这些问题,让我们来解决您最初的问题。请求没有运行的最可能原因是您没有订阅
http
observable。可观察对象是惰性的,因此如果您不通过
.subscribe
@ngrx/effects
订阅它,它就不会做任何事情

因此,假设您正在调用
CreateGroup
,如下所示:

this.groupsService.CreateGroup(data);
在您订阅以下内容之前,此操作不会起任何作用:

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

  // Here you can react to the post, close a modal, redirect or whatever you want.
});
我还建议在api调用中添加一个
.first()
,因为这样可以避免在组件被销毁时手动取消订阅Observable

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

constructor(private appApi: AppApi) {}

...

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

  // Do something
});

我希望这是有帮助的。

不要在HTTP POST中字符串化POST数据。只需传递对象

最终能够使用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);
    }
>CreateGroup(GroupObj:Group):承诺{
返回此。\u http
.post(this.u GroupsUrl,JSON.stringify(GroupObj),{headers:this.headers})
.toPromise()
.then(res=>res.json().data作为组)
.接住(这个.把手错误);
}

这个的值是多少。\u http
?当您执行此代码时,浏览器控制台/网络显示什么?除了我的console.log信息外,什么都没有…我在网络选项卡中根本看不到POST call。我试着跟随;let headers=新的头({'Content-Type':'application/json'});let options=newrequestoptions({headers:headers,body:JSON.stringify(GroupM),方法:“post”});返回此.http.post(this._GroupsUrl,JSON.stringify(GroupM),{headers:headers}).map((Response:Response)=>Response.JSON()[0]).do(data=>console.log('Service Response:'+data)).catch(this.handleError);当我附加调试器时,它在内部调用http.prototype.post,在内部调用requestOption和URL,方法变为null。现在我知道为什么我没有在网络选项卡中看到它,但不明白为什么会这样happening@jatin:请从您实际调用的位置添加组件代码
this.groupsService.CreateGroup(data).subscribe(() => {

  // Here you can react to the post, close a modal, redirect or whatever you want.
});
constructor(private appApi: AppApi) {}

...

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

  // Do something
});
>  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);
    }