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++ 代码会一直按我的预期工作,还是不能保证执行顺序?

Angular 4 加载器无法按预期工作

Angular Material步进线性验证无法按预期工作

proxy.conf.json在Angular 6中无法按预期工作

ComboBox DataSource 没有按我预期的那样工作[重复]