Hi there, is there any known open source http client multiplatform library that doesn't use corounti...
a
Hi there, is there any known open source http client multiplatform library that doesn't use corountines under the hood??
b
Wouldn't count on it. There's just no demand for such a thing when we have ktor
e
I think OkHttp alphas have KMP support
j
for the API but there's no backing implementation yet. and as it's a blocking API it will never work on JS.
also ktor is an HTTP client abstraction not an HTTP client and it's API is not that great so there's lots of room to compete with it
b
I dunno, I think the API has improved significantly with 2.0
j
both of those things can be true
a
I asked this question with an intention of not reinventing the wheel, but with enough motive to start an open source project. @jw Based on your knowledge, (combining the use of Okhttp, URLConnection, Ktor Client, fetch, e.t.c) what do you think would be the best (or what combination would yield the best) API for a http client, that is not blocking but doesn't depend on coroutines?
j
i'm not sure there's a reason to create such a thing and the ergonomics of using it would be worse than both of those two options
a
Not sure there is a reason? What if you include Kotlin/Js's bundle size problem? what if you include a better http client abstraction than the one ktor offers? Still no reason to create such a thing?
b
IMHO I'd rather have the community efforts focussed on a single KMP client and iterating on that than fragmented accross multiple libraries. KMP networking is already quite demanding, so the more people are focussed on it the better.
Also are you sure coroutines are to blame for ktor bundle size bloat on js? (I literally have no idea)
j
nah competition is good
👆 1
you see the same thing with Android and Jetpack libraries where there's this blind allegiance to them when a majority are simply not that great
a
@Big Chungus currently,
suspend
functions are very unforgiving in kotlin/js world, the more you have them the worse it gets. Using ktor requires you to create suspend functions to call them which makes the bundle larger and larger
b
Sounds like more of a kotlin.js compiler problem to be honest. But I digress, not using them would avoid having the compiler to bloat the app in the first place.
a
Let me show you a piece of code, that has nothing to do with ktor but suspend functions Given the kotlin class
Copy code
class AdderCoroutine {
    suspend fun one() = 1
    suspend fun two() = one() + 1
}
it compiles down to
Copy code
$twoCOROUTINE$0.prototype = Object.create(CoroutineImpl.prototype);
  $twoCOROUTINE$0.prototype.constructor = $twoCOROUTINE$0;
  //endregion
  function $twoCOROUTINE$0(_this__1828080292, resultContinuation) {
    CoroutineImpl.call(this, resultContinuation);
    this._this__1828080292__1 = _this__1828080292;
  }
  $twoCOROUTINE$0.prototype.doResume_5yljmg_k$ = function () {
    var suspendResult = this._get_result__3382885006_f31376_k$();
    $sm: do
      try {
        var tmp = this._get_state__3614753120_b8zcm8_k$();
        switch (tmp) {
          case 0:
            this._set_exceptionState__118868437_8fc1n_k$(2);
            this._set_state__1256591060_i39zdo_k$(1);
            suspendResult = this._this__1828080292__1.one_tuyife_k$(this);
            if (suspendResult === _get_COROUTINE_SUSPENDED__2870145053()) {
              return suspendResult;
            }

            continue $sm;
          case 1:
            var ARGUMENT = suspendResult;
            return ARGUMENT + 1 | 0;
          case 2:
            throw this._get_exception__1672948706_ro13he_k$();
        }
      } catch ($p) {
        if (this._get_exceptionState__1662596297_rhv7ih_k$() === 2) {
          throw $p;
        } else {
          this._set_state__1256591060_i39zdo_k$(this._get_exceptionState__1662596297_rhv7ih_k$());
          this._set_exception__4196179798_3fu58l_k$($p);
        }
      }
     while (true);
  };
  $twoCOROUTINE$0.$metadata$ = {
    simpleName: '$twoCOROUTINE$0',
    kind: 'class',
    interfaces: []
  };
  function AdderCoroutine() {
  }
  AdderCoroutine.prototype.one_tuyife_k$ = function ($cont) {
    return 1;
  };
  AdderCoroutine.prototype.two_hxbbm8_k$ = function ($cont) {
    var tmp = new $twoCOROUTINE$0(this, $cont);
    tmp._set_result__3294305178_cat9z_k$(Unit_getInstance());
    tmp._set_exception__4196179798_3fu58l_k$(null);
    return tmp.doResume_5yljmg_k$();
  };
  AdderCoroutine.$metadata$ = {
    simpleName: 'AdderCoroutine',
    kind: 'class',
    interfaces: []
  };
😱 1
b
I wonder why they didn't back that with promises on js?
a
Given the class
Copy code
class AdderPromise {
    fun one(): Promise<Int> = Promise.resolve(1)
    fun two(): Promise<Int> = one().then { it + 1 }
}
compiles down to
Copy code
function AdderPromise$one$lambda() {
    return function () {
      return 1;
    };
  }
  function AdderPromise$two$lambda() {
    return function (it) {
      return it + 1 | 0;
    };
  }
  function AdderPromise() {
  }
  AdderPromise.prototype.one_2d0m_k$ = function () {
    return promise(AdderPromise$one$lambda());
  };
  AdderPromise.prototype.two_2gy4_k$ = function () {
    var tmp = this.one_2d0m_k$();
    return then(tmp, AdderPromise$two$lambda());
  };
  AdderPromise.$metadata$ = {
    simpleName: 'AdderPromise',
    kind: 'class',
    interfaces: []
  };
j
because promises can't be canceled
👍 1
a
The coroutines case get even worse with more suspension point @Big Chungus
r
Why don't you create a client library without suspending functions, which will be implemented from scratch on K/JS and use Ktor client and coroutines on all other platforms?
a
That seems reasonable if you ask me
r
You can even take coroutines-free K/JS http client directly from KVision sources 😉 And just implement other platforms with Ktor and some mpp Promise implementation.
a
I already have an MPP promise implementation (called it Pending<T> BTW). Let me take a look at the K/JS http client there and see
g
"Promise can't be cancelled" -> You could provide a wrapper for JS that will plug an AbortSignal in the exported function and transmit the cancellation from coroutines to AbortSignal. We generate this pattern in KustomExport, so that JS can use fetch() method and we can cancel it from common code.
👍 1