#rxjs
Вопрос:
У меня есть вопрос, как вы обертываете обычный код синхронизации внутри наблюдаемого. Давайте возьмем этот пример:
let isCalling = false;
function makeHttpCall(url) {
isCalling = true;
return rxJsFetch(url).pipe(tap(() => (isCalling = false)));
}
Проблема с этой функцией заключается в том, что isCalling
флаг будет установлен независимо от того, подписывается кто-то или нет. Я этого не хочу (потому что он еще не звонит). Чтобы бороться с этим, я обычно делаю что-то вроде:
let isCalling = false;
function makeHttpCallWrapped(url) {
return of(null).pipe(
mergeMap(() => {
isCalling = true;
return rxJsFetch(url).pipe(tap(() => (isCalling = false)));
}),
);
}
И это работает, isCalling
устанавливается только после подписки.
Проблема с этим кодом заключается в том, что он не очень элегантен и не понятен для тех, кто начинает с RxJS. Мой вопрос к вам таков: как вы с этим справляетесь? Есть ли в RxJS что-то, о чем я не знаю, что справляется с этим более изящно?
Ответ №1:
Оператор отсрочки RxJS
Отсрочка позволяет создать наблюдаемый при подписке. Это в точности более чистая версия того, что вы уже делаете.
let isCalling = false;
function makeHttpCall(url) {
return defer(() => {
isCalling = true;
return rxJsFetch(url).pipe(tap(() => (isCalling = false)));
});
}
Ответ №2:
Чтобы сделать это более изящным, я создаю вспомогательный метод fromFunction
:
import { of } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
import { SubscribableOrPromise } from 'rxjs/src/internal/types';
export function fromFunction<T>(func: () => SubscribableOrPromise<T>) {
return of(undefined).pipe(mergeMap(func));
}
А затем используйте его, как:
let isCalling = false;
function makeHttpCallWrapped(url) {
return fromFunction(() => {
isCalling = true;
return rxJsFetch(url).pipe(tap(() => (isCalling = false)));
});
}
Я вроде как чувствую, from
что тоже должен принимать такой вклад.