【问题标题】:Subscription mysteriously not triggering订阅神秘地没有触发
【发布时间】:2017-12-03 22:53:53
【问题描述】:

所以我正在使用 Angular 和 Firestore。出于某种原因,我可以在一个地方订阅可观察到的罚款,但不能在另一个地方订阅,我不知道为什么。我觉得可能是因为我曾经在某个地方订阅过它。我可以没有一个 同时运行订阅和使用 take(1) 还是什么?我没有收到任何错误,它只是停在那里。

private jobDoc: AngularFirestoreDocument<Job>;
job: Observable<Job>;


ngOnInit() {
  this.route.params.subscribe(jobId => {
    this.createJobPage().then(function(result){
      this.job.subscribe(job => {
        console.log('this works');
      });
    }.bind(this));
  });
}


// When I load the page we run this function
createJobPage() {
  return new Promise(function(resolve){
    this.getUser().then(user => {
      this.jobDoc = this.afs.doc(`accounts/${user['cid']}/jobs/jobId`);
      this.job = this.jobDoc.valueChanges();
      this.job.take(1).subscribe(job => {
        console.log('this works');
      });
      resolve();
    });
  }.bind(this));
}


// Clicking a button saves the info
saveNewJob() {
  this.getUser().then(function(user) {
    console.log('this works, and shows "this.job" is an observable', this.job);
    this.jobDoc.update({id: 1})   // If I add this line it all works
    this.job.take(1).subscribe(job => {
      console.log('this does not work'); // This doesn't work
    });
    console.log('This works');
  }.bind(this));
}

-------- 更新 --------

我认为这是一个错误。这有效:

this.jobDoc.update({id: 1})
this.job.take(1).subscribe(job => {
  console.log('this works');
});

但如果我删除 jobDoc 更新它就不起作用,像这样:

this.job.take(1).subscribe(job => {
  console.log('this works');
});

所以看来如果我想订阅这个,我需要先给jobDoc 一点刺激才能唤醒它……有人知道为什么吗?

【问题讨论】:

    标签: angular observable angularfire2 google-cloud-firestore


    【解决方案1】:

    也许可以尝试使用first() 而不是take(1),取 1 发出 1 并取消订阅。

    【讨论】:

    • 编辑了代码,但仍然遇到同样的问题。 this.job 在我尝试订阅之前 console.log 它显示为可观察的,所以我认为它在范围内。订阅似乎并没有触发它。我确实觉得这可能是一个范围问题,但不确定如何,因为当我 console.log 时,我得到了 observable 而不是 undefined
    • 好的,我稍微编辑了上面的代码。还是不行。查看更改,这绝对不是范围问题,因为我可以在引用上使用更新没问题。
    【解决方案2】:

    这真的让我很好奇,所以我去了 firebase 源文档并找到了这个 https://github.com/angular/angularfire2/blob/master/src/firestore/observable/fromRef.ts

    valueChanges 是由这些函数构建的,关键部分是:

    export function fromRef<R>(ref: firebase.firestore.DocumentReference | 
        firebase.firestore.Query) {
        return _fromRef<typeof ref, R>(ref).share();
    }
    

    这是一个共享的 observable,因此一旦完成,所有当前和未来的订阅者都会完成。所以最初的 take(1) 完成了它,然后任何未来的订阅者都不会从中得到任何东西,这就是重新引用它起作用的原因,因为它重新创建了共享的 observable。

    【讨论】:

      【解决方案3】:

      要修复它,我只是重新设置了this.job,但我不知道为什么我需要这样做。也许是一个错误?如果有人知道,LMK

      this.job = this.jobDoc.valueChanges();
      this.job.take(1).subscribe(snap => {
        console.log('WORKED!');
      });
      

      【讨论】:

      • 在我看来,您遇到了某种范围问题,其中“工作”没有在同一范围内定义。如果你停止绑定“this”而只使用箭头函数会发生什么
      • 我刚刚将所有函数换成了箭头函数并删除了所有绑定。仍然有同样的问题,但没有bind(this) 到处都干净得多,哈哈。谢谢!
      【解决方案4】:

      不是bug,this.jobthis.jobDoc的引用

      经过进一步审查,saveNewJob() 在没有触发器的情况下添加了订阅者。

      添加this.jobDoc.update 是触发器:)

      saveNewJob() {
        this.getUser().then(function(user) {
          console.log('this works, and shows "this.job" is an observable', this.job);
          this.jobDoc.update({id: 1})   // If I add this line it all works
          this.job.take(1).subscribe(job => {
            console.log('this does not work'); // This doesn't work
          });
          console.log('This works');
        }.bind(this));
      }
      

      【讨论】:

      • this.job.take(1).subscribe() 不会立即触发吗?如果不是,我不确定为什么它在我第一次初始化它时第一次起作用,但不是以后。 this.job 在我第一次订阅createJobPage() 时立即触发,当页面加载时,但不是稍后我点击保存时...
      • this.jobDoc = this.afs.doc(`accounts/${user['cid']}/jobs/jobId`); 是触发第一个的行,valueChanges() 同步该路径上的所有数据,只要路径上的项目更新并且有订阅者,就会触发事件。