仅当还不是 Observable 时才转换为 Observable
Transform to Observable only if not already Observable
我有一张支票,需要合并 2 个支票:
- 第一个检查是可观察的,以判断用户是否已登录
- 第二个检查是一个函数,它可以 return 布尔值或 Observable
是否有更优雅的方式将一个值包装在一个可观察的对象中,如果它还不是可观察的?
或者当第二个是 Observable 时,有没有办法将第一个检查与第二个检查结合起来?
或者仍然以更有效的方式重构所有这些?
当然,此代码是模拟我在真实应用程序中获得的内容的示例(请参阅代码中的注释)。
const getRandomBool: () => boolean = () => Math.random() >= 0.5;
const getRandomCheck: () => boolean | Observable<boolean> = () => {
return getRandomBool() ? getAsyncCheck() : getSyncCheck();
};
const myFunction = (): Observable<boolean> | boolean => {
// First check telling if user is logged, which the UserService returns as Observable<boolean>
return of(getRandomBool())
.pipe(
mergeMap((isLogged) => {
// This is the check which can be either boolean or Observable<boolean>
const myCheck = getRandomCheck();
return isLogged
? iif(() => typeof myCheck === 'boolean', of(myCheck), myCheck)
: of(!1)
})
)
};
``
例子
const { of, iif, pipe, isObservable , operators: { mergeMap } } = rxjs;
const getAsyncCheck = () => of(Boolean(Math.floor(Math.random() * 2)));
const getSyncCheck = () => Boolean(Math.floor(Math.random() * 2));
const getRandomBool = () => Boolean(Math.floor(Math.random() * 2));
const getRandomCheck = () => {
return getRandomBool() ? getAsyncCheck() : getSyncCheck();
};
const myFunction = () => {
return of(getRandomBool())
.pipe(
mergeMap((isLogged) => {
const myCheck = getRandomCheck();
const result = isLogged ? iif(() => isObservable(myCheck), myCheck, of(myCheck)) : of(false);
return result;
})
).subscribe(result => {
console.log(result)
})
};
myFunction();
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.js"></script>
我会强制 randomCheck
到 observable,然后使用 exhaustMap
来处理返回正确的 observable; of(false)
当 isLogged = false
或 randomCheck$
否则:
const myFunction = (): Observable<boolean> => {
const randomCheck$ = isObservable(randomCheck) ? randomCheck : of(randomCheck);
return getIsLogged().pipe(
exhaustMap(isLogged => isLogged ? randomCheck$ : of(false)),
// take(1)
);
};
如果getIsLogged()
没有完成,我认为你需要使用take(1)
来angular守卫。
如果“myCheck”是 Observable 并使用 forkJoin
,先检查如何?
const myFunction: () => Observable<boolean> = () => {
let myCheck = getRandomCheck();
myCheck = isObservable(myCheck) ? myCheck : of(myCheck);
return forkJoin([of(getRandomBool()), myCheck])
.pipe(
map(([logged, yourCheck]) => {
return logged ? yourCheck : !1;
})
)
}
编辑
正如 BizzyBob 所建议的那样,如果 myCheck 是异步的并且跨度很大,它可能会毫无意义地影响整个执行。
所以我们可以使用switchMap
来避免这个问题
const myFunction: () => Observable<boolean> = () => {
let myCheck = getRandomCheck();
myCheck = isObservable(myCheck) ? myCheck : of(myCheck);
return of(getRandomBool())
.pipe(
switchMap((logged: boolean) => {
return logged ? myCheck : of(!1);
})
)
}
我有一张支票,需要合并 2 个支票:
- 第一个检查是可观察的,以判断用户是否已登录
- 第二个检查是一个函数,它可以 return 布尔值或 Observable
是否有更优雅的方式将一个值包装在一个可观察的对象中,如果它还不是可观察的? 或者当第二个是 Observable 时,有没有办法将第一个检查与第二个检查结合起来? 或者仍然以更有效的方式重构所有这些?
当然,此代码是模拟我在真实应用程序中获得的内容的示例(请参阅代码中的注释)。
const getRandomBool: () => boolean = () => Math.random() >= 0.5;
const getRandomCheck: () => boolean | Observable<boolean> = () => {
return getRandomBool() ? getAsyncCheck() : getSyncCheck();
};
const myFunction = (): Observable<boolean> | boolean => {
// First check telling if user is logged, which the UserService returns as Observable<boolean>
return of(getRandomBool())
.pipe(
mergeMap((isLogged) => {
// This is the check which can be either boolean or Observable<boolean>
const myCheck = getRandomCheck();
return isLogged
? iif(() => typeof myCheck === 'boolean', of(myCheck), myCheck)
: of(!1)
})
)
};
``
例子
const { of, iif, pipe, isObservable , operators: { mergeMap } } = rxjs;
const getAsyncCheck = () => of(Boolean(Math.floor(Math.random() * 2)));
const getSyncCheck = () => Boolean(Math.floor(Math.random() * 2));
const getRandomBool = () => Boolean(Math.floor(Math.random() * 2));
const getRandomCheck = () => {
return getRandomBool() ? getAsyncCheck() : getSyncCheck();
};
const myFunction = () => {
return of(getRandomBool())
.pipe(
mergeMap((isLogged) => {
const myCheck = getRandomCheck();
const result = isLogged ? iif(() => isObservable(myCheck), myCheck, of(myCheck)) : of(false);
return result;
})
).subscribe(result => {
console.log(result)
})
};
myFunction();
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.js"></script>
我会强制 randomCheck
到 observable,然后使用 exhaustMap
来处理返回正确的 observable; of(false)
当 isLogged = false
或 randomCheck$
否则:
const myFunction = (): Observable<boolean> => {
const randomCheck$ = isObservable(randomCheck) ? randomCheck : of(randomCheck);
return getIsLogged().pipe(
exhaustMap(isLogged => isLogged ? randomCheck$ : of(false)),
// take(1)
);
};
如果getIsLogged()
没有完成,我认为你需要使用take(1)
来angular守卫。
如果“myCheck”是 Observable 并使用 forkJoin
,先检查如何?
const myFunction: () => Observable<boolean> = () => {
let myCheck = getRandomCheck();
myCheck = isObservable(myCheck) ? myCheck : of(myCheck);
return forkJoin([of(getRandomBool()), myCheck])
.pipe(
map(([logged, yourCheck]) => {
return logged ? yourCheck : !1;
})
)
}
编辑
正如 BizzyBob 所建议的那样,如果 myCheck 是异步的并且跨度很大,它可能会毫无意义地影响整个执行。
所以我们可以使用switchMap
来避免这个问题
const myFunction: () => Observable<boolean> = () => {
let myCheck = getRandomCheck();
myCheck = isObservable(myCheck) ? myCheck : of(myCheck);
return of(getRandomBool())
.pipe(
switchMap((logged: boolean) => {
return logged ? myCheck : of(!1);
})
)
}