Typically, APIs that are sometimes sync and sometimes async are called "z̲̗̼͙̥͚͛͑̏a̦̟̳͋̄̅ͬ̌͒͟ļ̟̉͌ͪ͌̃̚g͔͇̯̜ͬ̒́o̢̹ͧͥͪͬ" - unpredictable, hard to maintain, hard to understand. The general best practice is that a function should always be async, or always sync, but never the twain shall meet.
Relevant: http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony On Sun, Feb 3, 2019 at 4:49 PM Isiah Meadows <[email protected]> wrote: > 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 >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

