programing

이전에 방출된 값을 기준으로 실행 방지

prostudy 2022. 4. 1. 18:25
반응형

이전에 방출된 값을 기준으로 실행 방지

자동 검색에서 빈 검색 결과를 얻는 경우 노로 다운된 검색 쿼리를 사용한 후속 쿼리는 차단되어야 한다.예: '빨간색'에 대한 검색이 비어 있는 경우, '빨간색'에 대한 검색은 의미가 없다.

쌍방향()과 스캔() 연산자를 사용해 보았다.코드 조각:

import { tap, switchMap, filter, pairwise, scan, map } from 'rxjs/operators';

this.searchForm.get('search').valueChanges
  .pipe(
    switchMap( queryString => this.backend.search(queryString))
  )
  .subscribe()

간단한 시나리오가 지정된 업데이트:뒷말에는 '사과'라는 말밖에 없다.사용자가 검색 문자열을 입력하는 중(switchMap()에서 요청이 중단되지 않음):

  1. 'a' -------> 백엔드 콜 리턴스 'apple'
  2. 'ap' ------------------ 백엔드 콜 리턴스 'apple'
  3. 'app' ----> 백엔드 콜 리턴 'apple'
  4. 'appl' ----> 백엔드 콜 리턴스 'apple'
  5. 'apple' ---> 백엔드 콜 리턴 'apple'
  6. 'apple p' ----> 백엔드 콜 리턴 비어 있음
  7. 'apple pi' ----> 백엔드 콜 리턴 비어 있음
  8. '애플 파이' --> 백엔드 콜 리턴 비어 있음

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

반응형