我正在开发一个Angular(v4)应用程序。与任何其他Web应用程序一样,此应用程序也有HTTP
个请求,对于每个请求,我都订阅了获取数据并在UI上显示它们。我一直在阅读async
管道的使用情况以及为什么它比subscribe
更好。根据我的阅读,它肯定比普通的subscribe
方法有好处,我确信我应该在我的应用程序中使用它,但我不知道如何用这个aync
管道构建我的应用程序而不是subscribe
。让我发布我的应用程序的结构:
我有一个服务层,可以向后端发出Http
请求,例如:
一些-service.component.ts
@Injectable()
export class SomeService {
constructor(private http: HttpClient) {
}
getSomething() {
return this.http.get(`${this.baseUrl}/${'test'}`);
}
}
上面的服务为我的组件提供了一个Observable,我通常订阅它,如下所示:
一些-component.ts
@Component({
selector: 'some-app',
templateUrl: './some.component.html',
styleUrls: []
})
export class SomeComponent {
constructor(private someService: SomeService) {
}
getSomething() {
this.someService
.getSomething()
.subscribe(
// the first argument is a function which runs on success
(data) => {
// DO SOME DATA TRANSFORMATION HERE
},
// the second argument is a function which runs on error
(err: HttpErrorResponse) => {
this.exceptionService.errorResponse(err);
},
// the third argument is a function which runs on completion
() => {
// MAKE SOME FUNCTION CALL
}
);
}
}
以上是我如何订阅一般HTTP
响应的一般结构。我想摆脱这个subscribe
并使用async
代替。但是,我的问题是,我在收到数据(如上所示)或某个时间data transformation
完成I make some function call from the
(如上所示)时做了一些observer
并且通过此类操作,我不确定一旦切换到async
,我将如何进行这些操作。
对于数据转换,我想,我可以在我的服务中做到这一点(虽然不确定)但是我现在如何进行函数调用。
任何输入都将受到高度赞赏。如果我的问题需要更多澄清,也请告诉我。谢谢!
答案 0 :(得分:2)
我将以更通用的方式根据您的代码回答
<强> foo.service.ts 强>
awk '
FNR==1 { # get the column number of PREDICT column for each file
for(i=1;i<=NF;i++)
if($i=="PREDICT")
p=i # set it to p
}
$p==646 { # if p==646, we have a match
print FILENAME # print the filename
nextfile # and move on to the next file
}' file1 file2 # all the candicate files
在地图操作员中,您可以进行操作并返回新状态
<强> foo.component.ts 强>
导入rxjs @Injectable()
export class FooService {
constructor(private _http:HttpClient){ }
public getFoo():Observable<any> {
return this._http.get(`${API_URL}`).map(r => r.json());
}
}
运算符以调用最后的方法
finally
<强> foo.html 强>
import 'rxjs/add/operators/finally';
export class FooComponent {
public bar$:Obervable<any>;
constructor(private _foo:FooService){}
getBar(): void {
this.bar$ = this._foo.getFoo()
.finally(() => {
// INVOKE DESIRED METHOD
});
}
}
这将创建div包装元素并为其提供visiblity隐藏选项,因此不需要? '猫王'运营商
您还可以根据您的要求修改ngIf表达式
答案 1 :(得分:1)
当您使用observable时,您可以使用一个非常常见的运算符将传入的数据转换为其他内容:地图运算符(documentation here)。 “ Map运算符将您选择的函数应用于源Observable发出的每个项目,并返回一个Observable,它发出这些函数应用程序的结果。”
some-service.component.ts(已修改)
// Don't forget this, or it will cause errors
import 'rxjs/add/operator/map';
@Injectable()
export class SomeService {
constructor(private http: HttpClient) {
}
getSomething() {
return this.http.get(`${this.baseUrl}/${'test'}`)
.map(data => transformData(data));
}
一些-component.ts
@Component({
selector: 'some-app',
templateUrl: './some.component.html',
styleUrls: []
})
export class SomeComponent {
constructor(private someService: SomeService) { }
getSomething() {
this.someService
.getSomething()
.subscribe(
// the first argument is a function which runs on success
(data) => {
// DO SOMETHING WITH DATA TRANSFORMED HERE
},
// the second argument is a function which runs on error
(err: HttpErrorResponse) => {
this.exceptionService.errorResponse(err);
},
// the third argument is a function which runs on completion
() => {
// MAKE SOME FUNCTION CALL
}
);
}
}
请注意,您还可以在some-component.ts中再次使用map运算符(在导入之后)。你也可以决定一次使用它,只在some-component.ts中使用它。或者您可以将函数传递给this.someService.getSomething(myFunction)来转换数据。请参阅下面的服务实现。
// Don't forget this, or it will cause errors
import 'rxjs/add/operator/map';
@Injectable()
export class SomeService {
constructor(private http: HttpClient) {
}
getSomething(myFunction) {
return this.http.get(`${this.baseUrl}/${'test'}`)
.map(data => myFunction(data));
}
要使用异步管道,请将Observable存储在属性中。
import { Component, OnInit } from '@angular/core'
@Component({
selector: 'some-app',
templateUrl: './some.component.html',
styleUrls: []
})
export class SomeComponent implements OnInit {
myObservable;
constructor(private someService: SomeService) { }
ngOnInit() {
this.myObservable = this.getSomething();
}
getSomething() {
return this.someService.getSomething();
}
}
然后,将异步管道应用于您的模板(documentation here):
<p>{{ myObservable | async }}</p>
或者,正如所说的Optiq(当你处理对象的例子时):
<div *ngFor="let a of myObservable | async">
<p>{{ a.whatever }}</p>
</div>
请注意,您不能将异步管道应用于函数。
最后,您可以处理收到数据的情况。见下文:
import { Component, OnInit } from '@angular/core'
@Component({
selector: 'some-app',
templateUrl: './some.component.html',
styleUrls: []
})
export class SomeComponent implements OnInit {
myObservable;
constructor(private someService: SomeService) { }
ngOnInit() {
this.myObservable = this.getSomething();
}
getSomething() {
const obs = this.someService.getSomething();
obs.subscribe((data) => {
// Handle success
}, (err) => {
// Handle error
}, () => {
// Make some function call
})
return obs;
}
}
答案 2 :(得分:0)
async pipe
在您的模板绑定中应用,如此
<div *ngFor="let a of yourData | async">
<p>{{a.whatever}}</p>
</div>
如果您不知道a
是您想要调用每个数组的名称,yourData
是您班级中您正在迭代的变量的名称从
我不会说这是&#34;更好&#34;而不是使用subscribe()
,因为它不是做同样事情的另一种方式。事实上,async
管道可以帮助你的绑定处理订阅,因为当一个组件加载它时,它可能会在数据到达之前调用变量的值,这会给你一堆undefined
错误或者看不到console.log()
中的任何内容,即使您在模板中看到它具有约束力。
你试图通过嗅探async
管道来消除什么头痛?这听起来像你需要了解的其他东西,你还不知道如何要求它,这是尝试发现它。
答案 3 :(得分:0)
1)您可以创建linked answer来进行数据转换(custom pipe)
答案 4 :(得分:0)
优势:
注意::您一定会喜欢这样,代码仅供参考。请逐步实施以下代码,以测试您的API数据。
// call your imports
@Component({
selector: 'some-app',
template: '
<ng-container *ngIf="data$ | async as data">
<input [value]="data.new" />
<div *ngFor="let val of data">
// some more todo things
</div>
</ng-container>
'
})
export class SomeComponent {
data$: Observable<data>;
}