为什么HttpParams在角度4.3中不能在多行中工作

时间:2017-08-02 11:25:01

标签: angular

从Angular 4.3开始,他们引入了HttpClient而不是Http。 在HttpClient我无法将URLSearchParams用于url查询参数。而不是URLSearchParams我正在使用HttpParams

这项工作

 var params = new HttpParams().append('a', '1').append('b', '2');

但为什么这不起作用

var params = new HttpParams();
params.append('a', '1');
params.append('b', '2');

5 个答案:

答案 0 :(得分:73)

新的HTTP客户端使用不可变请求对象及其所有组成部分,如HttpParamsHttpHeaders。要了解原因,请参阅Why is http request and all its constituent parts like HttpHeaders and HttpParams are immutable或阅读文章Insider’s guide into interceptors and HttpClient mechanics in Angular

这就是为什么append方法合并参数,在每次调用HttpParams时返回合并的append对象的新实例的原因:

  /**
   * Construct a new body with an appended value for the given parameter name.
   */
  append(param: string, value: string): HttpParams { 
        return this.clone({param, value, op: 'a'}); 
  }

  private clone(update: Update): HttpParams {
    const clone = new HttpParams({encoder: this.encoder}); <-------
    clone.cloneFrom = this.cloneFrom || this;
    clone.updates = (this.updates || []).concat([update]);
    return clone;                                          <--------
  }

所以这里:

var params = new HttpParams().append('a', '1').append('b', '2');
带有append参数的b使用append参数更新a返回的对象。

采用这种方法

var params = new HttpParams();
params.append('a', '1');
params.append('b', '2');

append始终更新HttpParams的初始状态,并且所有中间append操作都被有效忽略。

所以你必须使用之前返回的值:

var params = new HttpParams();
params = params.append('a', '1');
params = params.append('b', '2');

或使用fromObject的快捷方式:

let searchParams = new HttpParams({
    fromObject: {
        query: query,
        sort: sort,
        order: order
    }
});

const modified = req.clone({params: searchParams});

或直接在请求中使用setParams方法:

const modified = req.clone({setParams: {'query': query, 'sort': sort, 'order': order}});

此外,从5.1.x开始,您可以直接传递对象而不是HttpParams的实例:

const params = {
  'a': '1',
  'b': '2'
};

this.http.get('...', { params })

答案 1 :(得分:22)

为此起作用

var params = new HttpParams();
params.append('a', '1');
params.append('b', '2');

这必须改为

var params = new HttpParams();
params = params.append('a', '1');
params = params.append('b', '2');

它可以循环并动态添加

答案 2 :(得分:8)

5.0.0-beta.6(2017-09-03)新功能(accept object map for HttpClient headers & params)可用。

现在我们可以直接传递对象而不是HttpParams

const params = {
  'a': '1',
  'b': '2'
};

this.http.get('...', { params })

或代替HttpHeaders

http.get('/url', {
   headers: {'My-Header': 'header value'}
})

答案 3 :(得分:2)

实际上@Maximus对HttpParams对象的不变性做了很好的解释,你所需要的只是简单地用循环内的克隆替换params

假设您有零到多 params可用,存储在类似于以下结构的数组中:

"params": [
  {
    "key": "p1",
    "value": "v1"
  },
  {
    "key": "p2",
    "value": "v2"
  }
]

根据上面的信息,以下帮助函数应该有所帮助:

export const getHttpParams = (params: Array<any>): HttpParams => {
  let res = new HttpParams();

  for (const item of params)
    res = res.append(item.key, item.value);

  return res;
};

<强>用法

const backend = 'http://httpstat.us/200';
const params = getHttpParams(backend.params);

return this.http.get(`${backend}`, { params });

希望它有所帮助!

答案 4 :(得分:2)

我在这篇文章中尝试了所有其他方法,但收效甚微。所以我将params链接到HttpParams单例并调用toString()以返回string类型。然后我可以将它传递给http.get(),一切似乎都可以正常工作来构建url参数。这是我的ng -v

$ ng -v
    _                      _                 ____ _     ___
   / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
  / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
 / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
/_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
           |___/
@angular/cli: 1.4.2
node: 8.5.0
os: linux x64
@angular/animations: 4.4.3
@angular/cdk: 2.0.0-beta.10
@angular/common: 4.4.3
@angular/compiler: 4.4.3
@angular/core: 4.4.3
@angular/forms: 4.4.3
@angular/http: 4.4.3
@angular/material: 2.0.0-beta.10
@angular/platform-browser: 4.4.3
@angular/platform-browser-dynamic: 4.4.3
@angular/router: 4.4.3
@angular/cli: 1.4.2
@angular/compiler-cli: 4.4.3
@angular/language-service: 4.4.3
typescript: 2.3.4

这是一个适合我的例子:

// Simplified for example (I'm using Redux and won't go into all that)
private downloadState = { requestType: 'Auction', fileType: 'CSV' };

getStuffFromApi(): Observable<any> {
    const { requestType, fileType } = this.downloadState;
    const apiRoot = 'http://www.example.com';

    const params: string = new HttpParams()
        .set('RequestType', requestType)
        .set('FileType', fileType)
        .set('AuctionType', auctionType)
        .set('BackorderDay', backorderDay)
        .toString();

    return this.http.get(apiRoot, { params })
        .map(res => res.json())
        .catch(err => Observable.of(err.json()));

}