角 5 | ASYNC,多个数据绑定冲突 1 CRUD 服务

分享于2023年03月15日 angular angular-services angular5 asynchronous 问答
【问题标题】:Angular 5 | ASYNC, conflict in multiple data binding 1 CRUD service角 5 | ASYNC,多个数据绑定冲突 1 CRUD 服务
【发布时间】:2018-03-15 00:15:47
【问题描述】:

我创建了一个“主 CRUD 服务”。

当我在 2 个不同的组件中使用它从传递的 URL 获取数据并使用 | 时,它失败了异步

当在一个组件中检索数据时,另一个组件更改为该流

每个组件都有一个声明的 Observable 但名称不同,为什么会发生这种情况?

组件1 HTML


Component1 请求

export class Component1 implements OnInit {
  public component1: Observable;
  public gridState: State = {
    skip: 0,
    take: 100
  };

  constructor(private fetchDataEditService: FetchDataEditService) {
  }

  public requestClick(): void {
    this.component1 = this.fetchDataEditService.map((data: any) =>
      ({
        data: data.results,
        total: data.count,
      })
    )

    this.fetchDataEditService.read(this.url, this.gridState);
  }

Component2 HTML


Component2 请求

export class Component2 implements OnInit {
  public component2: Observable;
  public gridState: State = {
    skip: 0,
    take: 100
  };

  constructor(private fetchDataEditService: FetchDataEditService) {
  }

  public requestClick(): void {
    this.component2 = this.fetchDataEditService.map((data: any) =>
      ({
        data: data.results,
        total: data.count,
      })
    )

    this.fetchDataEditService.read(this.url, this.gridState);
  }

fetchDataEditService

@Injectable()
export class FetchDataEditService extends BehaviorSubject {
  constructor(private http: HttpClient) {
    super([]);
  }

  public data: any[] = [];

  public read(url: string, state: DataSourceRequestState = {}) {

    const data = [];

    this.fetch('', url, state)
      .do((data: any) =>
        ({
          data: data.results,
          total: data.count,
        })
      )
      .subscribe((data: any) => {
        super.next(data);
      });

  };

  public save(url: string, state: DataSourceRequestState, data: any, isNew?: boolean) {
    const action = isNew ? CREATE_ACTION : UPDATE_ACTION;

    this.reset();

    this.fetch(action, url, state, data)
      .subscribe(() => this.read(url, state), () => this.read(url, state));
  }

  public remove(url: string, state: DataSourceRequestState, data: any) {
    this.reset();
    this.fetch(REMOVE_ACTION, url, state, data)
      .subscribe(() => this.read(url, state), () => this.read(url, state));
  }

  public resetItem(url: string, dataItem: any) {
    if (!dataItem) { return; }

    const originalDataItem = this.data.find(item => item.djangoid === dataItem.djangoid);

    Object.assign(originalDataItem, dataItem);

    super.next(this.data);
  }

  private reset() {
    this.data = [];
  }

  private fetch(action: string = '', url: string = '', state?: DataSourceRequestState, data?: any): Observable {

    const queryStr = `${toDataSourceRequestString(state)}`;

    const httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'application/json'
      })
    }

    if (action == "") {
      return this.http
        .get(`${API_URL + url}/?${queryStr}`)
        .retry(3).pipe(catchError(this.handleError))
    }

    if (action == "create") {
      return this.http
        .post(API_URL + url + '/', data, httpOptions)
        .pipe(catchError(this.handleError))
    }

    if (action == "update") {
      alert
      return this.http
        .put(API_URL + url + '/' + data.djangoid + '/', data, httpOptions)
        .pipe(catchError(this.handleError))
    }

    if (action == "destroy") {
      return this.http
        .delete(API_URL + url + '/' + data.djangoid + '/', httpOptions)
        .pipe(
          tap(res => console.log(`deleted id=${data.djangoid}`)),
          catchError(this.handleError))
    }
    throw Error('Internal REST Command Error')

  }
  private handleError(error: Response) {
    console.error(error);
    return Observable.throw(error.json() || 'Server Error');
  }

}

任何想法

谢谢

编辑 1 - 响应在哪里提供服务

我在 DataModule 中提供服务,我将其导入到 CoreModule 中,最后将其导入到我的 AppModule 中

Data.module.ts

import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';

import { FetchDataEditService } from './edit.service';
import { SeniorSandpitService } from './seniorsandpit.service';
import { UtilsService } from './utils.service';

const SERVICES = [
  FetchDataEditService,
  SeniorSandpitService,
  UtilsService,
];

@NgModule({
  imports: [
    CommonModule,
  ],
  providers: [
    ...SERVICES,
  ],
})
export class DataModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: DataModule,
      providers: [
        ...SERVICES,
      ],
    };
  }
}

Core.Module.ts

import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common';
import { throwIfAlreadyLoaded } from './module-import-guard';
import { DataModule } from './data/data.module';
import { AnalyticsService } from './utils/analytics.service';

const NB_CORE_PROVIDERS = [
  ...DataModule.forRoot().providers,
  AnalyticsService,
];

@NgModule({
  imports: [
    CommonModule,
  ],
  exports: [
  ],
  declarations: [],
})
export class CoreModule {
  constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
    throwIfAlreadyLoaded(parentModule, 'CoreModule');
  }

  static forRoot(): ModuleWithProviders {
    return {
      ngModule: CoreModule,
      providers: [
        ...NB_CORE_PROVIDERS,
      ],
    };
  }
}

  • 您的服务在哪里提供?我问这个是因为我的猜测是它是在应用程序的某个地方提供的,在这种情况下,我想我知道发生了什么。
  • 针对此问题编辑的问题

【解决方案1】:

我认为您的问题在于您的两个组件共享完全相同的服务实例。这通常不会成为问题,但是您的服务本身就是一个主题,因此任何导致数据被广播出去的调用都会被两个组件看到。这是因为 Angular 中的服务在提供它们的地方是单例的(除非您注册工厂来创建它们)。

我有一种感觉,如果您在配置对象中为每个组件提供服务,您将不会看到这种行为,因为那时它们将是单独的主题。

@Component({
    ...
    providers: [FetchDataEditService]
})

我建议您查看 Dependency Injection 上的 Angular 文档。

【讨论】: