【问题标题】:Why does data from .subscribe() first return an empty object before filling the object with data?为什么 .subscribe() 中的数据在用数据填充对象之前首先返回一个空对象?
【发布时间】:2020-01-01 03:31:38
【问题描述】:

我正在使用 Observables 从后端获取数据。在我的函数中,我订阅了我的 observable,当我 console.log() 传回的数据似乎返回了两次。首先是一个空对象,然后是我期望的数据。

这给我带来了问题,因为我正在尝试使用 for...in 循环将数据的键与另一个对象的键进行比较,以便我可以匹配这些值。我得到一个 TypeError: Cannot read property '0' of undefined 因为数据首先返回一个空对象。这让我很困惑,因为我在订阅的回调方法中执行 console.log() 。

回调方法的重点不就是等到数据到达吗?

我尝试了一个回调函数以及将 for...in 直接放在订阅中,但由于对象首先返回空,所以都不起作用。我做错了什么?

this.memberService.memberDetails.subscribe(member => {
    this.member = member;
    this.member_id = this.authService.loggedInUser.app_user_data.member_id;
    this.parseAddress();
    console.log('member subscribe', this.member);
    this.formData();
});

// 更新:会员服务代码

 private _memberDetails = new BehaviorSubject<any>({});

 public get memberDetails() {
    return this._memberDetails.asObservable();
}

// 注意 console.log() 已经触发了两次

formData() {
    for (const flatProfileKey in this.profileData['permanent_address'][0]) {
        for (const key in this.member['addresses'][0]) {

            if (flatProfileKey === key) {
                this.profileData[key] = this.flatProfile[key];
                console.log('profileData perament_address', this.profileData['permanent_address'][0])

            }
        }

    }
}

// 如果我尝试遍历数据,它会返回一个未定义的错误,大概是因为订阅首先返回一个空对象,所以没有什么可以循环的

【问题讨论】:

  • 请在您有memberDetails 设置的地方分享您的memberService 代码。或者,您可以使用filter rxjs 运算符来过滤不需要的数据。
  • 请看更新。

标签: javascript angular for-loop observable


【解决方案1】:

这是预期的,因为您将初始值设置为 BehaviorSubject 以在此处为空对象:

private _memberDetails = new BehaviorSubject<any>({});

如果您不需要初始值,可以考虑使用Subject 而不是BehaviorSubject。 在此处阅读有关BehaviorSubject 的更多信息:https://www.learnrxjs.io/subjects/behaviorsubject.html

【讨论】:

    【解决方案2】:

    这是按预期工作的。

    如果之前没有发出过值,行为主体将重新发出上次发出的值或默认值。

    现在,看到您将默认值作为空对象提供给 BehaviorSubject。由于您将默认值传递给它,它会将此默认值发送给所有订阅者。

    当您检索数据并更改 BehaviorSubject 的值时,它会再次将新数据发送给订阅者。

    此外,如果您不打算将任何默认值作为默认值传递给 BehaviourSubject,则不能这样做。

    在这里,您有两种选择:

    1. 您可以添加额外的if 来检查发出的值是否为默认值{}。并据此处理这些东西。代码如下:

      formData() { 
          if(this.profileData['permanent_address']) {
              // Data fetched, do something
              for (const flatProfileKey in this.profileData['permanent_address'][0]) { 
      
              } 
          }
          else {
              // If data is not fetched, do something if you want to
          }
      }
      
    2. 您可以使用Subject 代替不需要默认值的BehaviorSubject。由于它没有值,因此在获取数据之前不会发出它。只需更改以下行:

      private _memberDetails = new BehaviorSubject<any>({})
      

      private _memberDetails = new Subject<any>()
      

      这将按照您的预期工作。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2021-10-29
      • 1970-01-01
      • 2020-11-24
      • 1970-01-01
      • 1970-01-01
      • 2016-07-20
      • 1970-01-01
      • 2020-12-23
      • 1970-01-01
      相关资源
      最近更新 更多