Closed borodinalive closed 1 year ago
Either
only works synchronously, even if you use async/await inside map
it's still a Promise and it's much like using async/await inside Array.map
- it doesn't work.
I suggest you look at the EitherAsync docs, the API is exactly the same as Either but you can work with Promises and async/await.
The most funny thing is it code works :)) and Idea's linter is OK with it. But not with chain
Is it right?
async execute(state: StateDto): Promise<NetworkError | SellerDetailsDto> {
return await this.stateManager?.getUser(state)
.map((user) => user.seller?.id)
.map(async (sellerId) => {
return EitherAsync(() => this.userService.getUserSeller(sellerId ?? ''));
})
.extract();
}
So it works too. :-))
Without more context I can't help you much, what does this.stateManager?.getUser(state)
return? An Either, Maybe, EitherAsync?
I would prefer a codepen/stackblitz etc with code I can work with.
Unfortunately I don't know how to use it. There was no need earlier. :((
this.stateManager?.getUser(state)
returns Either<any, UserDto>
this.userService.getUserSeller(sellerId ?? '')
returns Promise<Either<NetworkError, SellerDetailsDto>>
Based on what you've given me here's how the implementation must look like:
interface User { sellerId: number }
interface SellerDetails { id: number }
declare const getUser: () => Either<Error, User>
declare const getUserSeller: (sellerId: number) => Promise<Either<Error, SellerDetails>>
const execute = (): Promise<Error | SellerDetails> =>
EitherAsync.liftEither(getUser())
.map((user) => user.sellerId)
.chain((sellerId) => getUserSeller(sellerId))
.run()
.then((either) => either.extract())
Hope that helps! The key here is that if you have an Either and you want to do async stuff with it you can use EitherAsync.liftEither
and then you're free to chain Promises. Also if you decide to return EitherAsync directly it's less code to wrap and unwrap values:
const execute = (): EitherAsync<Error, SellerDetails> =>
EitherAsync.liftEither(getUser())
.map((user) => user.sellerId)
.chain((sellerId) => getUserSeller(sellerId))
const result: Either<Error, SellerDetails> = await execute()
It is a HUUUGE HELP! Thank you very much!!!
Real world examples are extremely needed!
That's the final working result:
async execute(state: StateDto): Promise<NetworkError | SellerDetailsDto> {
return EitherAsync.liftEither(this.stateManager.getUser(state))
.map((user) => user.seller?.id)
.chain((sellerId) => this.userService.getUserSeller(sellerId ?? ''))
.run()
.then((either) => either.extract());
}
}
BTW If my first WORKING use case is not expectable it is ponentialy a bug or a promising feature! ;-)
It's seems to me, that there is a problem in second map. I suppose that it must be a method like flatMap with async function getting a parameter and returning another EITHER. And this flatMap must return an flattened EITHER with result of function inside flatMap. The most close method is
chain
, but it refuse to work with promises with an error:Argument of type '(sellerId: string | undefined) => Promise<NetworkError | SellerDetailsDto>' is not assignable to parameter of type '(value: string | undefined) => Either<unknown, unknown>'.
So. How do it the right way?