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

时间:2018-03-15 00:15:48

标签: angular asynchronous angular5 angular-services

我创建了一个" Master CRUD服务"。

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

在1个组件中检索数据时,其他组件将更改为该流

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

Component1 HTML

<kendo-grid [data]="component1| async" />

组件1请求

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

  constructor(private fetchDataEditService: FetchDataEditService) {
  }

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

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

Component2 HTML

<kendo-grid [data]="component2| async" />

组件2请求

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

  constructor(private fetchDataEditService: FetchDataEditService) {
  }

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

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

fetchDataEditService

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

  public data: any[] = [];

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

    const data = [];

    this.fetch('', url, state)
      .do((data: any) =>
        (<GridDataResult>{
          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<GridDataResult> {

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

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

    if (action == "") {
      return this.http
        .get<GridDataResult>(`${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 <ModuleWithProviders>{
      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 <ModuleWithProviders>{
      ngModule: CoreModule,
      providers: [
        ...NB_CORE_PROVIDERS,
      ],
    };
  }
}

1 个答案:

答案 0 :(得分:1)

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

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

def multiply(intent_request):

    invoice = try_ex(lambda: intent_request['currentIntent']['slots']['Invoice'])
    advance = try_ex(lambda: intent_request['currentIntent']['slots']['CashAdvance'])
    datedue = try_ex(lambda: intent_request['currentIntent']['slots']['DueDate'])
    sector = try_ex(lambda: intent_request['currentIntent']['slots']['Sector'])

    session_attributes = intent_request['sessionAttributes'] if intent_request['sessionAttributes'] is not None else {}

    last_confirmed_loan = try_ex(lambda: session_attributes['lastConfirmedLoan'])
    if last_confirmed_loan:
        last_confirmed_loan = json.loads(last_confirmed_loan)
    confirmation_context = try_ex(lambda: session_attributes['confirmationContext'])

    loan = json.dumps({
        'Invoice': invoice,
        'CashAdvance': advance,
        'DueDate': datedue,
        'Sector': sector
    })

    session_attributes['currentLoan'] = loan


    if intent_request['invocationSource'] == 'DialogCodeHook':
        # Validate any slots which have been specified.  If any are invalid, re-elicit for their value
        validation_result = validate_loan_details(intent_request['currentIntent']['slots'])
        if not validation_result['isValid']:
            slots = intent_request['currentIntent']['slots']
            slots[validation_result['violatedSlot']] = None

            return elicit_slot(
                session_attributes,
                intent_request['currentIntent']['name'],
                slots,
                validation_result['violatedSlot'],
                validation_result['message']
            )

        if sector is not None:    
            return {
                'dialogAction': {
                    'type': 'elicit_slot',
                    'fulfillmentState': 'ElicitSlot',
                    'message': {
                        'contentType': 'PlainText',
                        'content': 'What sector?'
                    },            
                    'responseCard': {
                      "version": 3,
                      "contentType": "application/vnd.amazonaws.card.generic",
                      "genericAttachments": [
                        {
                          "title": "Company Sectors",
                          "subtitle": "Select one",
                          "buttons": [
                            {
                              "text": "Company A",
                              "value": "32"
                            },
                            {
                              "text": "Company B",
                              "value": "33"
                            },
                            {
                              "text": "Company C",
                              "value": "34"
                            }
                          ]
                        }
                      ]
                    }
                }
            }

        session_attributes['currentLoan'] = loan
        return delegate(session_attributes, intent_request['currentIntent']['slots'])


    logger.debug('LoanDetails under={}'.format(loan))

    try_ex(lambda: session_attributes.pop('currentLoan'))
    session_attributes['lastConfirmedLoan'] = loan

    return close(
        session_attributes,
        'Fulfilled',
        {
            'contentType': 'PlainText',
            'content': 'Multiply can purchase your invoice at $' + invoice + ' for a fee of $_________, are you down for it?'
        }
    )

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