Используя Kovenant от Kotlin, я продолжаю использовать повторяющийся код, используя Deferred

При использовании Kovenant от Kotlin я получаю много кода, который является образцом:

fun foo(): Promise<SomeResultType, Exception> { val deferred = deferred<SomeResultType, Exception>() try { // bunch of work that deferred.resolve() or deferred.reject() } catch (ex: Exception) { deferred.reject(ex) } return deferred.promise } 

Я знаю, что я могу использовать task { ... } для асинхронного обещания, и это позаботится об этом, но когда я уже асинхронно или записываю адаптеры в другие классы асинхронизации, я хочу использовать экземпляр с Deferred .

Есть что-то вроде task { ... } которая откладывает вместо этого и заботится о дополнительной работе?

Примечание. Этот вопрос намеренно написан автором и отвечает на него ( Self-Answered Questions ), так что решения для интересных проблем разделяются в SO.

Вы можете использовать тот же шаблон, что и функция расширения Lock.withLock() и Closeable.use() , которая предназначена для того, чтобы обернуть лямбда с Closeable.use() обработкой и вывести типы, чтобы избежать шаблонов вокруг вашего экземпляра с Deferred .

Функция withDeferred :

 fun <T : Any?> withDeferred(codeBlock: Deferred<T, Exception>.() -> Unit): Promise<T, Exception> { val deferred = deferred<T, Exception>() try { deferred.codeBlock() } catch (ex: Exception) { deferred.reject(ex) } return deferred.promise } 

Которая затем может использоваться как:

 fun foo(): Promise<SomeType, Exception> { return withDeferred { // bunch of work that calls resolve() or reject() } } 

Однако, это не так хорошо, когда вы напрямую связываете обещания. Проблемы возникают, когда у вас нет четких типов, которые могут быть выведены для дженериков вашего Deferred экземпляра. Таким образом, для их цепочки может потребоваться, чтобы на сайте вызова указывались обобщения, например:

 fun foo(): Promise<SomeType, Exception> { return withDeferred<PreviousType> { // bunch of work that calls resolve(PreviousType) or reject() } bind { previous -> withDeferred<SomeType> { // bunch of work that calls resolve(SomeType) or reject() } } }