代码之家  ›  专栏  ›  技术社区  ›  London804

为什么.subscribe()中的数据在用数据填充对象之前首先返回空对象?

  •  0
  • London804  · 技术社区  · 6 年前

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

    这给我带来了一个问题,因为我正试图使用for…in循环将数据的键与另一个对象的键进行比较,以便匹配值。我得到一个类型错误:无法读取未定义的属性“0” 因为数据首先返回一个空对象。这让我很困惑,因为我在订阅的回调方法中执行console.log()。

    回调方法的整个点不是要等到数据到达之后才开始吗?

    我尝试了一个回调函数,并将for…直接放在subscribe中,但都不起作用,因为对象首先返回空值。我做错什么了?

    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()已触发两次

    notice the console.log() has fired twice

    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])
    
                }
            }
    
        }
    }
    

    //如果我试图循环访问数据,它会返回一个未定义的错误,可能是因为subscribe首先返回一个空对象,所以没有任何要循环访问的对象

    If I try to loop through the data it returns an undefined error presumably because the subscribe first returns an empty object so there is nothing to loop through

    2 回复  |  直到 6 年前
        1
  •  1
  •   User3250    6 年前

    当您将初始值设置为 BehaviorSubject 要在此处清空对象:

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

    如果不需要初始值,可以考虑使用 Subject 而不是 . 了解更多信息 行为主体 在这里: https://www.learnrxjs.io/subjects/behaviorsubject.html

        2
  •  1
  •   sanketd617    6 年前

    这按预期工作。

    行为主题将重新发出上一个发出的值,或者如果没有发出上一个值,则重新发出默认值。

    现在,请注意,您正在将默认值提供给 BehaviorSubject 作为空对象。由于要向其传递默认值,它将向所有订阅服务器发出此默认值。

    当您检索数据并更改 行为主体 然后它将再次向订阅服务器发出新数据。

    此外,如果您想将Nothing作为默认值传递给 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 而不是 行为主体 不需要默认值。因为它没有值,所以在获取数据之前它不会发出值。只需更改以下行:

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

      private _memberDetails = new Subject<any>()
      

      这会像你期望的那样有效。

    希望这有帮助。