我创建了一个" 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,
],
};
}
}
答案 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文档。