이전에 방출된 값을 기준으로 실행 방지
자동 검색에서 빈 검색 결과를 얻는 경우 노로 다운된 검색 쿼리를 사용한 후속 쿼리는 차단되어야 한다.예: '빨간색'에 대한 검색이 비어 있는 경우, '빨간색'에 대한 검색은 의미가 없다.
쌍방향()과 스캔() 연산자를 사용해 보았다.코드 조각:
import { tap, switchMap, filter, pairwise, scan, map } from 'rxjs/operators';
this.searchForm.get('search').valueChanges
.pipe(
switchMap( queryString => this.backend.search(queryString))
)
.subscribe()
간단한 시나리오가 지정된 업데이트:뒷말에는 '사과'라는 말밖에 없다.사용자가 검색 문자열을 입력하는 중(switchMap()에서 요청이 중단되지 않음):
- 'a' -------> 백엔드 콜 리턴스 'apple'
- 'ap' ------------------ 백엔드 콜 리턴스 'apple'
- 'app' ----> 백엔드 콜 리턴 'apple'
- 'appl' ----> 백엔드 콜 리턴스 'apple'
- 'apple' ---> 백엔드 콜 리턴 'apple'
- 'apple p' ----> 백엔드 콜 리턴 비어 있음
- 'apple pi' ----> 백엔드 콜 리턴 비어 있음
- '애플 파이' --> 백엔드 콜 리턴 비어 있음
7.와 8.에 대한 백엔드 호출은 불필요하다. 6.이 이미 비어있기 때문이다.따라서 후속 통화는 생략할 수 있다.내 의견으로는 메모가 필요하다.
불필요한 백엔드 콜(http)을 방지하고 싶다.rxjs로 이것을 성취할 수 있는 방법은 없을까?
이것은 흥미로운 사용 사례로, 다음과 같은 몇 가지 상황 중 하나이다.mergeScan
유용하다.
기본적으로 이전 검색어와 이전 원격 호출 결과를 기억하려고 하며, 그 조합에 따라 다른 원격 전화를 걸어야 할지 아니면 그냥 돌아가야 할지를 결정하게 된다.EMPTY
.
import { of, EMPTY, Subject, forkJoin } from 'rxjs';
import { mergeScan, tap, filter, map } from 'rxjs/operators';
const source$ = new Subject();
// Returns ['apple'] only when the entire search string is contained inside the word "apple".
// 'apple'.indexOf('app') returns 0
// 'apple'.indexOf('apple ap') returns -1
const makeRemoteCall = (str: string) =>
of('apple'.indexOf(str) === 0 ? ['apple'] : []).pipe(
tap(results => console.log(`remote returns`, results)),
);
source$
.pipe(
tap(value => console.log(`searching "${value}""`)),
mergeScan(([acc, previousValue], value: string) => {
// console.log(acc, previousValue, value);
return (acc === null || acc.length > 0 || previousValue.length > value.length)
? forkJoin([makeRemoteCall(value), of(value)]) // Make remote call and remember the previous search term
: EMPTY;
}, [null, '']),
map(acc => acc[0]), // Get only the array of responses without the previous search term
filter(results => results.length > 0), // Ignore responses that didn't find any results
)
.subscribe(results => console.log('results', results));
source$.next('a');
source$.next('ap');
source$.next('app');
source$.next('appl');
source$.next('apple');
source$.next('apple ');
source$.next('apple p');
source$.next('apple pi');
source$.next('apple pie');
setTimeout(() => source$.next('app'), 3000);
setTimeout(() => source$.next('appl'), 4000);
라이브 데모: https://stackblitz.com/edit/rxjs-do457
검색 후"apple "
더 이상 원격 전화는 없다.또한, 당신이 다른 용어 "app"를 검색해 보면 3초 후에 다시 원격으로 전화를 걸 수 있다.
필터 연산자를 사용할 수 있음:
this.searchForm.get('search').valueChanges.pipe(
filter(query => query)
switchMap(query => this.backend.search(queryString))
)
여기서 이 메커니즘을 사용해 보십시오: RxJS-Editor
코드 공유가 작동하지 않았으므로 여기서 코드를 받으십시오.
const { of } = Rx;
const { filter } = RxOperators;
of('foo1', 'foo2', undefined, undefined, 'foo3').pipe(
filter(value => value)
)
실패한 검색을 모두 유지하고 HTTP가 호출된 경우에도 현재 검색이 실패하는지 여부를 확인하려는 것 같음.나는 이것을 하나의 흐름에서 가지는 어떤 우아한 방법을 생각할 수 없다. 그러나 두 개의 흐름으로.
_failedStreams = new Subject();
failedStreams$ = _failedStreams.asObservable().pipe(
scan((acc, curr) => [...acc, curr], []),
startWith('')
);
this.searchForm.get('search').valueChanges
.pipe(
withLatestFrom(failedStreams$),
switchMap([queryString, failedQueries] => {
return iif(() => failedQueries.find(failed => failed.startsWith(queryString)) ?
of('Not found') :
callBackend(queryString);
)
}
)
.subscribe()
callBackend(queryString) {
this.backend.search(queryString)).pipe(
.catchError(err => if(error.status===404) {
this._failedStreams.next(queryString);
// do something with error stream, for ex:
throwError(error.status)
}
)
}
코드는 테스트되지 않았지만, 당신은 아이디어를 얻는다.
참조URL: https://stackoverflow.com/questions/56752871/prevent-execution-based-on-previously-emitted-value
'programing' 카테고리의 다른 글
index.js:1375 Warning: Material-UI: 탭 구성 요소에 제공된 '/' 값이 잘못됨.이 값을 가진 탭 하위 탭 없음 (0) | 2022.04.02 |
---|---|
vuex 스토어에서 vue-resource($ttp) 및 vue-router($route)를 사용하는 방법? (0) | 2022.04.01 |
Vuetify 탭을 Vue-Router와 함께 사용하는 방법 (0) | 2022.04.01 |
방법 대 Vue에서 계산된 방법 (0) | 2022.04.01 |
Flask-SQ에서 ID별 레코드를 삭제하는 방법라헬미 (0) | 2022.04.01 |