You could move the async part into a helper function and call that from a
sync function you instead expose. I've used this trick more than once, and
although it is a bit of boilerplate, it works well enough.
On Sun, Feb 3, 2019 at 18:40 #!/JoePea <[email protected]> wrote:
> I often find myself enjoying async functions until the time comes when I
> don't want to await anything, and I want the call stack to be sync (i.e. I
> don't want to defer if I don't have to).
>
> But, async functions always return a Promise. So I find my self converting
> my async functions back into normal functions so that I can return
> non-Promise values, this way the caller can wait only if I return a
> promise, otherwise continue synchronously.
>
> Here's an example function in one of my classes:
>
> ```js
> initWebGL() {
> if (this.__glLoading) return false
> this.__glLoading = true
>
> // order of the if-else matters!
> if (this.__glUnloading) return
> Promise.resolve().then(A.bind(this))
> else if (this.__glLoaded) return false
>
> A.call(this)
>
> function A() {
> // ... load stuff (omitted for brevity) ...
> }
>
> return true
> }
> ```
>
> then the caller (f.e. a subclass) only needs to wait when a promise is
> returned:
>
> ```js
> initWebGL() {
> const superResult = super.initWebGL()
> if (superResult instanceof Promise) return
> superResult.then(A.bind(this))
> if (!superResult) return false
>
> A.call(this)
>
> function A() {
> // ... subclass loads stuff (omitted for brevity) ...
> }
>
> return true
> }
> ```
>
> This is just one example, but in general I find many cases where I want to
> run synchronously most of the time, and only sometimes have to defer
> (whether by choice or not).
>
> So I am losing out on the nice `await` syntax just because I can not do
> what I want to do with `async`/`await`.
>
> What if async functions could have some way to continue synchronously, and
> return non-Promise values?
>
> Or, what if we could have some sort of Promise API that would cause any
> callers to synchronously away, like in the following example, so that the
> change is not a breaking change, and async functions would still return
> Promises but the Promise could perhaps continue synchronously:
>
> ```js
> async function example() {
> return Promise.sync()
> }
> ```
>
> Then, in a caller, there would be no microtask deferral:
>
> ```js
> async function test() {
> await example()
> console.log('one')
> // implicit return is a Promise.sync() here.
> }
>
> function main() {
> test()
> console.log('two')
> }
> ```
>
> The output in this case would be:
>
> ```
> "one"
> "two"
> ```
>
> Note that in that example, we are _sure_ that `two` is logged after `one`
> because those async functions only ever use `Promise.sync()`.
>
> It would be good practice to use `await` regardless, because one may not
> know if the async function they are calling will return a
> non-`Promise.sync` value. So the `main` function is better written as
>
> ```js
> async function main() {
> await test()
> console.log('two')
> }
> ```
>
> In this case, everything still happens synchronously, but if the author of
> `example()` changes the implementation to return a non-sync Promise, then
> things will still run in the expected order. F.e.
>
> ```js
> async function example() {
> await fetch(...)
> }
> ```
>
> I keep finding scenarios where I want to avoid async unless I need async,
> but then I lose the convenient async/await syntax.
> _______________________________________________
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss
>
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss