【问题标题】:Problems with updating the view..when using service to service call更新视图的问题..使用服务到服务调用时
【发布时间】:2020-02-11 14:26:16
【问题描述】:

我使用应用服务来监听 pouchdb 的变化:

init() {
    const pouch = new PouchDB('app_data', {});
    const remoteDB = new PouchDB('http://xx.xx.xx.xx:35986/app_data', {
        skip_setup: true,
        auto_compaction: true,
        auth: {
          username: 'root',
          password: 'root'
        }
      });
    const sync = pouch.sync(remoteDB, {
      live: true,
      retry: true
    }).on('change', (info) => {
      this.facilityProtoService.update();
...

和另一个向视图发送数据的服务:

@Injectable()
export class FacilityProtoService {

  constructor() {}

  private pouch = new PouchDB('app_data', {});
  private facilityProtoStore = new Subject<any>();
  public facilityProto$ = this.facilityProtoStore.asObservable();

  public update() {
    console.log('[facilityProto] update');
    this.pouch.get('facilities')
      .then((res:any) => this.facilityProtoStore.next(res.structure))
  }
}

组件看起来像:

@Component({
  selector: 'zpa-facility-designer',
  template: `
    <p>facility-designer works!</p>
    <ng-container *ngFor="let key of test$ | async, trackBy: trackByFn">
      {{ key }}<br>
    </ng-container>
  `
})
export class FacilityDesignerComponent implements OnInit {

  test$: any;

  constructor(
    private facilityProtoService: FacilityProtoService
  ) {}

  ngOnInit() {
    this.test$ =  this.facilityProtoService.facilityProto$.pipe(tap(i => console.log(Object.keys(i))), map(i => Object.keys(i)))
  }

  trackByFn(index, item) {
    return index;
  }

}

点击操作符中的数据始终正确显示,但视图没有更新。

只要我在应用服务的构造函数中添加一个间隔函数,一切都可以正常工作,视图就会正确更新。

constructor(
    private facilityProtoService: FacilityProtoService
  ) {
    console.log('app service');
    setInterval(() => {}, 1000);
  }

这两个服务都是单例的,应用服务初始化由 app_initializer 触发。

任何想法为什么它适用于间隔?并且只在组件中而不在组件视图中?

编辑:当interval函数在组件的ngOnInit钩子中时也有效。

编辑 2:

我已经把这个例子做得更小了:

init() {
    this.changes.next(5);
    setTimeout(() => {
      this.changes.next(6)
    });
    this.pouch = new PouchDB('app', {});
    const remoteDB = new PouchDB('http://127.0.0.1:5984/app', {
      skip_setup: true,
      auth: {
        username: 'root',
        password: 'root'
      }
    });
    const sync = this.pouch
        .sync(remoteDB, {
          live: true,
          retry: true
        })
        .on('change', () => {
          this.changes.next(7)
        })
  }

值 5 和 6 在视图中正确显示... 7 仅在组件中。

【问题讨论】:

  • setInterval 触发更改检测周期。如果您使用异步管道在视图中订阅 this.test$,它还将更新视图,而无需像那样进行侧面破解。
  • 是的,这就是我的预期。但是如果没有那个 setInterval 触发器,它就不起作用。视图似乎存在由另一个服务触发的可观察数据的问题。
  • 我的猜测是,由于某种原因 this.test 没有得到新的参考。
  • 我已经用一个简单的例子更新了我的例子......所以它可能是 pouchdb 的问题?
  • 根据 pouchdb 文档中给出的示例,您可以尝试重写此 .on 事件我会尝试两件事:首先尝试将箭头函数替换为普通函数(以防万一事件有自己的上下文,箭头函数会搞砸),其次尝试将调用转换为适当的回调。如此处所示 => pouchdb.com/api.html#sync

标签: angular


【解决方案1】:

看起来语法有点不对劲。检查您的控制台输出是否有错误。试试

<ng-container *ngIf="test$ | async as tests">
    <ng-container *ngFor="let key of tests; trackBy: trackByFn">
        {{ key }}<br>
    </ng-container>
</ng-container>

【讨论】:

  • 尝试管道{{ key | json }}。可能是数据形状问题。
  • 我已经更新了示例(编辑 2)也许你会发现任何错误?
【解决方案2】:

我会尝试这样的方法来确保你得到一个新的参考:

test$: BehaviourSubject<any> = new BehaBehaviourSubject(null);

然后:

this.facilityProtoService.facilityProto$.pipe.subscribe(tap(i => { console.log(Object.keys(i));
test$.next(Object.keys(i);
});

【讨论】:

    猜你喜欢
    • 2014-07-06
    • 2013-04-06
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 2012-02-26
    • 2012-07-11
    • 2011-04-20
    • 2011-08-30
    相关资源
    最近更新 更多