angular - Rxjs 发现运算符不能处理 Observable 数组中的值
问题描述
我有一个服务,我将我的 http 有效负载投射到一个 Observable 数组,我希望能够调用该服务中的一个方法来对该 observable 采取行动。在我的情况下,我想确认一个 ID 存在于 Observable ID 的数组中。我已经对 stackoverflow 进行了一些研究,我认为这是因为我错误地处理了 find 运算符的返回(据我所知,它返回一个 observable)。
服务 :
@Injectable({
providedIn: 'root'
})
export class RuleFieldsService {
baseUrl: string;
relativeUrl: string;
httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
private rulefieldIdSub = new BehaviorSubject<any[]>([]);
private rulefieldIdStore: { ruleFieldIds: any } = { ruleFieldIds: [] };
rulefieldIds$ = this.rulefieldIdSub.asObservable();
constructor(private readonly http: HttpClient, @Inject(APP_BASE_HREF)
private readonly baseHref: string)
{
this.baseUrl = this.baseHref + environment.baseAPIUrl;
};
getRuleFields() {
this.relativeUrl = 'rulefields';
return this.http.get(this.baseUrl + this.relativeUrl);
}
getList(){
this.relativeUrl = 'rulefields';
this.http.get(this.baseUrl + this.relativeUrl + '/enabledropdown').subscribe(data => {
this.rulefieldIdStore.ruleFieldIds = data;
this.rulefieldIdSub.next(Object.assign({}, this.rulefieldIdStore).ruleFieldIds);
});
}
checkRuleFieldType(ruleFieldId) {
console.log('check method')
this.rulefieldIds$.pipe(find((id: any) => id === ruleFieldId)).subscribe(items => {
console.log("ID is in the list")
});
}
}
零件 :
@Component({
selector: 'app-rules-tab-wrapper',
templateUrl: './rules-tab-wrapper.component.html',
styleUrls: ['./rules-tab-wrapper.component.scss']
})
export class RulesTabWrapperComponent implements OnInit {
public selectedIndex;
public ruleFieldIds$: Observable<any[]>;
constructor(private rulesetService: RulesetService,
private rulefieldService: RuleFieldsService) { }
ngOnInit() {
this.rulefieldService.getList();
this.ruleFieldIds$ = this.rulefieldService.rulefieldIds$;
this.rulefieldService.checkRuleFieldType(15);
console.log(this.ruleFieldIds$ )
}
}
我查看了 Observable 以尝试更好地了解错误可能在哪里,但我无法对信息做出可操作的意义:
source: BehaviorSubject
closed: false
hasError: false
isStopped: false
observers: Array(1)
0: FindValueSubscriber
closed: false
destination: Subscriber {closed: false, _parentOrParents: null, _subscriptions: Array(1), syncErrorValue: null, syncErrorThrown: false, …}
index: 2
isStopped: false
predicate: (id) => id === ruleFieldId
source: Observable
source: BehaviorSubject {_isScalar: false, observers: Array(1), closed: false, isStopped: false, hasError: false, …}
_isScalar: false
__proto__: Object
syncErrorThrowable: true
syncErrorThrown: false
syncErrorValue: null
thisArg: undefined
yieldIndex: false
_parentOrParents: Subscriber
closed: false
destination: SafeSubscriber {closed: false, _parentOrParents: null, _subscriptions: null, syncErrorValue: null, syncErrorThrown: false, …}
isStopped: false
syncErrorThrowable: true
syncErrorThrown: false
syncErrorValue: null
_parentOrParents: null
_subscriptions: [FindValueSubscriber]
__proto__: Subscription
_subscriptions: [SubjectSubscription]
__proto__: Subscriber
length: 1
__proto__: Array(0)
thrownError: null
_isScalar: false
_value:
enableDropdownFor: (6) [15, 42, 55, 65, 67, 69]
提前感谢您的洞察力!
解决方案
您正在了解“查找”运算符如何有点偏离。它是一个过滤器,旨在过滤发出多个值的数据流,但在值与谓词匹配然后停止发出之前不会发出任何内容。
https://rxjs-dev.firebaseapp.com/api/operators/find
您的示例 observable 发出一个值,恰好是一个数组。您想要在函数中执行的操作是使用 rxjs 映射运算符,在其中您将拥有值数组,并使用标准数组的 find(或 findIndex),并返回一个布尔值。
我整理了一些堆栈闪电战来演示它,并附有一些评论。https://stackblitz.com/edit/angular-dra5wu?file=src%2Fapp%2Fapp.component.html
以下是我提到的一些概念和运算符:
export class ExampleService {
// start with "null" so we can filter that out, this way we know our get list has ran at least once if that's important
private rulefieldIdSub = new BehaviorSubject<any[]>(null);
// we skip the intial "null" value, this makes sure "getList" has populated the rules
rulefieldIds$ = this.rulefieldIdSub.asObservable().pipe(filter(ids => ids !== null));
getList(){
// making a fake list for example purposes, running in a set timeout so it takes a second
setTimeout(() => {
this.rulefieldIdSub.next([1,3,5,7,9])
}, 1000);
}
checkRuleFieldType(ruleFieldId): Observable<boolean> {
return this.rulefieldIds$.pipe(
// we're using the "map" operator to transform the result from the observable into something else
// https://rxjs-dev.firebaseapp.com/api/operators/map
map(ruleFieldIds => {
// map gets the full array of your ruleField ids, now we return if we found that id or not
return ruleFieldIds.findIndex(id => id === ruleFieldId) !== -1;
})
)
}
}
以及使用它的更新组件
export class AppComponent {
name = 'Angular';
rulefieldIds$: Observable<any[]>;
constructor(public exampleService: ExampleService) {
this.exampleService.getList();
this.rulefieldIds$ = this.exampleService.rulefieldIds$;
this.exampleService.checkRuleFieldType(15).subscribe(result => {
console.log("Do we have 15?", result)
});
this.exampleService.checkRuleFieldType(5).subscribe(result => {
console.log("Do we have 5?", result)
});
}
}
推荐阅读
- typescript - 如何使用 AWS CDK 将预先存在的用户推荐给您的托管策略和权限边界?
- react-native - 如何正确测试 Toast 是否已使用本机基础在本机反应中显示?
- hyperledger-fabric - Hyperledger Fabric - 无法将订购者添加到具有 v2.3 版本的通道。无法加入:无法从加入块确定集群成员资格
- python - 如何在 Python 中将变量的值更改为小写?
- r - 在R中的绘图中添加一条垂直线
- python - 如何在记事本rt++中使用python删除特定字符
- selenium - 登录 Webscraping Selenium
- list - 将索引附加到列表项(字符串)[Flutter]
- javascript - 刷新切换开关无法在暗模式设置中进行任何更改
- javascript - useEffect 被多次触发,我不知道要改变什么