Angular 订阅无法按我的预期工作
Posted
技术标签:
【中文标题】Angular 订阅无法按我的预期工作【英文标题】:Angular subscribes not working how I expect 【发布时间】:2021-06-05 12:02:45 【问题描述】:我在这里处于一个松散的结局,并试图了解角度订阅的工作流程。
我调用 API 并在响应中将数据设置在 behaviorSubject 中。这样我就可以在我的应用程序中订阅该数据。
通常我会在我的模板中使用异步管道,因为它会更干净,它会为我清除所有订阅数据。
所有方法都属于同一个类方法。
我的第一次尝试.....
exportedData: BehaviourSubject = new BehaviourSubject([]);
exportApiCall(id)
this.loadingSubject.next(true)
this.api.getReport(id).pipe(
catchError((err, caught) => this.errorHandler.errorHandler(err, caught)),
finalize(() => => this.loadingSubject.next(false))
).subscribe(res =>
this.exportedData.next(res)
)
export(collection)
let x = []
this.exportCollection(collection.id); /// calls api
this.exportedData.subscribe(exportData =>
if(exportData)
x = exportData
)
console.log(x)//// first time it's empthy, then it's populated with the last click of data
/// in the template
<button (click)="export(data)">Export</button>
我的问题是……
有一个具有不同 ID 的按钮列表。每个 ID 都进入 API 并返回某些数据。当我单击时,控制台日志首先给出一个空白数组。然后在我得到上一个(我最初点击的那个)数据集之后。
我显然没有正确理解订阅、管道和行为主题。我知道我得到了一个空白数组,因为我将行为主题设置为一个空白数组。
我的另一个尝试
export(collection)
let x = []
this.exportCollection(collection.id).pip(tap(res => x = res)).subscribe()
console.log(x) //// get blank array
exportApiCall(id)
return this.api.getReport(id).pipe(
catchError((err, caught) => this.errorHandler.errorHandler(err, caught))
)
【问题讨论】:
在第一个示例中,我不知道您的console.log(x)
到底在哪里?它在类方法之外的某个地方?此外,您的按钮有(click)="export(data)"
,但没有给出这样的方法。
方法已更新。控制台。你可以在方法中看到。 res 分配给 x。然后我在方法之外对 x 进行控制台,因为我想获取数据
【参考方案1】:
如果需要初始/默认值,您可以使用BehaviourSubject
。如果没有,您可以将其替换为Subject
。这就是为什么初始值为空数组的原因,因为默认情况下会调用一次 BehaviourSubject
。但是如果你使用subject
,它不会在api调用之前被调用,你也不会得到初始的空数组。
exportedData: BehaviourSubject = new BehaviourSubject([]);
此外,您可能不需要在这里订阅,而是直接返回它,这样您就可以避免使用上述主题。
exportApiCall(id)
this.loadingSubject.next(true);
return this.api.getReport(id).pipe(
catchError((err, caught) => this.errorHandler.errorHandler(err, caught)),
finalize(() => => this.loadingSubject.next(false))
);
-
Console.log(x) 需要在订阅中,因为订阅是异步的,我们不知道它何时可以完成。由于您需要这些数据,您可能需要在全局分数中声明。
export(collection)
// call api
this.exportApiCall(collection.id).subscribe(exportData =>
if (exportData)
this.x = exportData; // or maybe this.x.push(exportData) ?
console.log(this.x);
);
【讨论】:
谢谢。我已经尝试过这种方法,并且在 export method 中得到了许多响应。我想现在,我需要把它放在一个似乎已经控制了它的管道(take(1))中【参考方案2】:确保以下步骤。
-
最好在函数中添加
console.log
并检查是否有值。
打开您的 chrome 浏览器网络选项卡,查看服务端点是否成功。
检查来自端点的任何响应。
如果仍然无法识别,请使用下面的一个来检查您是否收到回复
public exportReport(collection): void
this.http.get(url+"/"+collection.id).subscribe(res=> console.log(res));
【讨论】:
【参考方案3】:不确定第一个示例 - console.log()
的位置以及方法(在按钮单击时分配)的作用 - 但对于第二个示例,您得到一个空数组,因为您的 observable 有延迟并且 TypeScript 不会等待其执行完成。
您很可能会看到您始终会在您的console.log()
中收到您之前的结果(在更新来自 API 的响应之后)。
要获得初始结果,您可以更新为:
public exportReport(collection): void
this.exportCollection(collection.id).pipe(take(1)).subscribe(res =>
const x: any = res;
console.log(x);
);
这将打印您当前的迭代/值。您还忘记结束收听订阅(通过取消订阅或执行运算符,例如take()
)。如果不结束收听,您稍后可能会得到意想不到的结果,或者应用程序可能会负载过重。
【讨论】:
似乎添加镜头似乎有所帮助。我以前从未使用过。现在阅读它是有道理的。谢谢你 很高兴有帮助:)以上是关于Angular 订阅无法按我的预期工作的主要内容,如果未能解决你的问题,请参考以下文章
带有 LocalDateTime 的 SpringBoot2 @DateTimeFormat 注释不能按我的预期工作
这个 C++ 代码会一直按我的预期工作,还是不能保证执行顺序?