Я создаю макет isuranceApp, и на этапе проверки otp мы должны ожидать два результата.
видите, я отправил запрос otp:
{
phoneNumber = "+101234123412",
secretKey = "abc"
}
и теперь пользователь может быть зарегистрированным пользователем, и в этом случае ответ будет:
{
userId = "000",
token = "abc101"
}
и если это не зарегистрированный пользователь, мы получим ответ:
{
message = "code is correct",
opCode = "xxx"
}
ну, как вы видите, есть два ожидаемых результата, и я не знаю, как с этим справиться с моей архитектурой, вставленной наполовину:
покажу вам процесс от viewModel до моей httpClientFactory
viewModel:
class OTPViewModel(
private val repository: AuthRepository
): ViewModel() {
private fun verify() {
viewModelScope.launch {
state = state.copy(isLoggingIn = true)
val result = repository.loginOTP(
otpCode = state.otpCode.text.toString().trim()
)
state = state.copy(isLoggingIn = false)
when(result) {
is Result.Error -> {
if (result.error == DataError.Network.CONFLICT) {
} else {
eventChannel.send(OTPEvent.Error(result.error.asUiText()))
}
}
// handle the secreteKey mechanism in sessionStorage
is Result.Success -> {
}
}
}
}
}
класс результата:
sealed interface Result {
data class Success(val data: D): Result
data class Error(val error: E): Result
}
inline fun Result.map(map: (T) -> R): Result {
return when(this) {
is Result.Error -> Result.Error(error)
is Result.Success -> Result.Success(map(data))
}
}
fun Result.asEmptyResult(): EmptyResult {
return map { }
}
typealias EmptyResult = Result
authRepository:
class AuthRepositoryImpl(
private val httpClient: HttpClient,
val sessionStorage: SessionStorage
): AuthRepository {
override suspend fun loginPhoneNumber(phoneNumber: String): EmptyResult {
val result = httpClient.post(
route = "/req",
body = LoginPhoneNumberRequest(
phoneNumber = phoneNumber
)
)
if (result is Result.Success) {
sessionStorage.setSecretKey(
secretKey = result.data.secretKey
)
}
return result.asEmptyResult()
}
override suspend fun loginOTP(otpCode: String): EmptyResult {
TODO("Not yet implemented")
}
}
httpClient:
suspend inline fun HttpClient.post(
route: String,
body: Request
): Result {
return safeCall {
post {
url(constructRoute(route))
setBody(body)
}
}
}
suspend inline fun safeCall(execute: () -> HttpResponse): Result {
val response = try {
execute()
} catch (e: UnresolvedAddressException) {
e.printStackTrace()
return Result.Error(DataError.Network.NO_INTERNET)
} catch (e: SerializationException) {
e.printStackTrace()
return Result.Error(DataError.Network.SERIALIZATION)
} catch (e: Exception) {
if (e is CancellationException) throw e
e.printStackTrace()
return Result.Error(DataError.Network.UNKNOWN)
}
return responseToResult(response)
}
suspend inline fun responseToResult(response: HttpResponse): Result {
return when (response.status.value){
in 200..299 -> Result.Success(response.body())
401 -> Result.Error(DataError.Network.UNAUTHORIZED)
408 -> Result.Error(DataError.Network.REQUEST_TIMEOUT)
409 -> Result.Error(DataError.Network.CONFLICT)
413 -> Result.Error(DataError.Network.PAYLOAD_TOO_LARGE)
429 -> Result.Error(DataError.Network.TOO_MANY_REQUESTS)
in 500..599 -> Result.Error(DataError.Network.SERVER_ERROR)
else -> Result.Error(DataError.Network.UNKNOWN)
}
}
fun constructRoute(route: String): String {
return when {
route.contains(BuildConfig.BASE_URL) -> route
route.startsWith("/") -> BuildConfig.BASE_URL + route
else -> BuildConfig.BASE_URL + "/$route"
}
}
Подробнее здесь: https://stackoverflow.com/questions/791 ... d-outcomes