我正在尝试使用async/await (这是第一次),我无法用它来控制自己。
我在这里做错了什么
tree.component.ts
export class TreeComponent implements OnInit {
private routeSub: any;
acronym: string;
flare: any[];
constructor(
private location: Location,
private route: ActivatedRoute,
private http: HttpClient,
private router: Router,
private fileTreeService: FileTreeService
) {
}
ngOnInit(): void {
this.routeSub = this.route.params.subscribe(
params => {
this.acronym = params.name
this.fileTreeService.getFileTree(params.name).subscribe(item => {
this.flare = item;
});
});filetree.service.ts
export class FileTreeService {
res: any;
constructor(private http: HttpClient) { }
async getFileTree(acronym) {
const headers = new HttpHeaders()
this.res = await this.http.get<any>(`${IP}/filetree/tree/`, { headers });
return this.res;
}
}我得到错误“属性‘’订阅‘不存在类型’承诺‘”在filetree.component.ts。我已经到了这条路的尽头,所以我要联系你们。提前谢谢。
更新:
谢谢你的帮助,它确实奏效了,但它并没有达到我想要达到的效果。难道不应该在继续执行代码之前等待结果吗?
ngOnInit(): void {
this.routeSub = this.route.params.subscribe(async (params) => {
this.acronym = params.name
this.flare = await this.fileTreeService.getFileTree(params.name).toPromise();
console.log("flare = ", this.flare);
});
let test = this.flare;
console.log("test = ", test);
} 根在flare被赋予一个值之前声明。这就是我的浏览器控制台发出的信息。
test = undefined
flare = {name: "data", children: Array(81)}发布于 2020-08-24 20:45:44
异步/等待承诺工作,因此,如果您使用httpClinet方法,您需要将返回值从可观察到的转换为通过toPromise方法承诺
filetree.service.ts
export class FileTreeService {
res: any;
constructor(private http: HttpClient) { }
getFileTree(acronym) {
const headers = new HttpHeaders()
// return an observable
return this.http.get<any>(`${IP}/filetree/tree/`, { headers })
}
}组件
ngOnInit(): void {
// mark the upper function with async
this.routeSub = this.route.params.subscribe(async (params) => {
this.acronym = params.name;
// now we can use await but we need to convert the observable to promise
this.flare = await this.fileTreeService.getFileTree(params.name).toPromise();
});
}您可以深入阅读教程https://javascript.info/async-await
更新的
我们可以使用异步标记ngOnInit,并在将主题转换为承诺之后使用等待所有的观察,在这种情况下,我们将不再使用订阅。
// mark the upper function with async
async ngOnInit(): Promise<void> {
// now we can use await but we need to convert the observable to promise
this.acronym = (await this.route.params.toPromise()).name;
this.flare = await this.fileTreeService.getFileTree(this.acronym).toPromise();
let test = this.flare; // => {name: "data", children: Array(81)}
console.log("test = ", test); // => {name: "data", children: Array(81)}
}发布于 2020-08-24 21:38:47
如果您是异步/反应性编程新手,我建议您不要将承诺和可观察性混为一谈。由于您使用的是角HttpClient模块,它返回一个可观察到的HTTP请求,所以我们只能继续使用它。
因此,您可以直接返回HTTP请求,而无需将其转换为承诺。Sidenote:与承诺相比,可观测数据还提供了对数据流和数据转换操作符的更多控制。
服务
export class FileTreeService {
res: any;
constructor(private http: HttpClient) { }
getFileTree(acronym): Observable<any> { // <-- `http.get()` returns an observable
const headers = new HttpHeaders();
return this.http.get<any>(`${IP}/filetree/tree/`, { headers });
}
}此外,现在您可以从this.fileTreeService.getFileTree()函数中观察到一个子函数,它依赖于来自另一个可观察到的this.route.params的通知。
在这种情况下,您可以使用RxJS高级映射操作符(如switchMap )从一个可观察到的映射到另一个,而不是像您正在做的那样具有多个内部订阅。现在,代码中的两个不同的数据流被简化为一个单一的数据流。流越小,潜在的内存泄漏越少。
组件
import { Subject } from 'rxjs';
import { switchMap, takeUntil } from 'rxjs/operators';
export class TreeComponent implements OnInit, OnDestroy {
private routeSub: any;
acronym: string;
flare: any[];
complete$ = new Subject<any>(); // <-- use to close open subscriptions
constructor(
private location: Location,
private route: ActivatedRoute,
private http: HttpClient,
private router: Router,
private fileTreeService: FileTreeService
) { }
ngOnInit(): void {
this.routeSub = this.route.params.pipe(
switchMap(params => { // <-- use `switchMap` to map from one observable to another
this.acronym = params.name;
return this.fileTreeService.getFileTree(params.name);
}),
takeUntil(this.complete$) // <-- close the subscription when `this.complete$` emits
).subscribe(
item => {
this.flare = item;
console.log(this.flare); // <-- correct log: will print the value of `this.flare`
},
error => {
// always good practice to handle errors from HTTP requests
}
);
console.log(this.flare); // <-- wrong log: will print `undefined`
}
ngOnDestroy() {
this.complete$.next(); // <-- close open subscriptions
}
}还请记住,由于this.flare变量是异步分配的,因此依赖它的所有语句都必须在订阅中。上面的代码使用不同的console.log()语句说明了这一点。订阅内部的订阅将打印正确的值,而订阅外的订阅将错误地打印this.flare持有的未定义的或旧的值。
我还使用RxJS takeUntil操作符关闭ngOnDestory()钩子中打开的订阅。您可以找到有关它的更多详细信息,以及处理未订阅这里的其他更简单的方法。
https://stackoverflow.com/questions/63568331
复制相似问题