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 <j...@trusktr.io> 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 > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss >
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss