Reflection to know if executed within a generator/async ?

Andrea Giammarchi andrea.giammarchi at gmail.com
Sat Dec 5 00:31:08 UTC 2015


Didn't know about that thread, interesting indeed.

My point in a TL;DR version: if the future is able to deal with sync code
satisfying async calls, why couldn't the future be even better giving old
sync code the backward-compatible ability to understand if it's invoked in
a future-like defined constrain such a generator or an async callback ...
 it looks like a limit from the future of the language, rather than a real
limit of what the current ES5/6 specification can provide.

Hence my `held` idea.

Regards

On Fri, Dec 4, 2015 at 7:13 PM, Bradley Meck <bradley.meck at gmail.com> wrote:

> Be very clear, this is interesting, but dangerous.
>
> I care very much but not in a positive way due to ironing out what would
> happen if the WHATWG Loader spec were to use Promises (either under the
> hood or explicitly). The amount of possible timing differences caused
> https://github.com/whatwg/loader/issues/54 which caused a huge refactor
> of the entire spec since timing implications of Promises are very different
> from synchronous code.
>
> My thoughts on things can be summed up as: if timing change
> implicity/based upon situations outside of your code -> side effects change
> -> code can break based upon when it is being used (rather than how it is
> being called).
>
> On Fri, Dec 4, 2015 at 11:31 AM, Andrea Giammarchi <
> andrea.giammarchi at gmail.com> wrote:
>
>> Eyes don't see, mind don't care?
>>
>> The fact await doesn't break, if that's the case, is cool and glorious.
>> The fact a consumed API would like to keep working with synchronous
>> projects and **realy** behave asynchronously with most modern one, is a
>> different thing.
>>
>> To better describe a common use case,  think about CommonJS
>>  `require('module')` API.
>>
>> There's no way it should break on all platforms (not jsut node and
>> browsers) that implemented CommonJS, it could still return a Promise,
>> through my `held` like idea, for Web and new async based code.
>>
>> async works with old code, old code cannot be promoted to async one. All
>> I am trying to explain is that I'd love to give well known, de-facto
>> standard, universally used APIs the ability to behave, for real,
>> asynchronously whenever the future of the language is available.
>>
>> How bad is that?
>>
>> Regards
>>
>>
>>
>>
>>
>>
>> On Fri, Dec 4, 2015 at 1:59 PM, Bradley Meck <bradley.meck at gmail.com>
>> wrote:
>>
>>> The more I read about this the more I think that `await` is what you
>>> want to change *not the behavior of functions*. Rephrased to what I think
>>> is being asked:
>>>
>>> If `await` encounters a non-thenable value, `Promise.resolve` the value
>>> before awaiting.
>>>
>>> Isn't this already the case?
>>>
>>> On Fri, Dec 4, 2015 at 2:44 AM, Andrea Giammarchi <
>>> andrea.giammarchi at gmail.com> wrote:
>>>
>>>> Jordan please let's avoid discussions about migration patterns, I'm
>>>> sure we've all done that and we all know how to. This is not the point of
>>>> my idea.
>>>>
>>>> Claude, again, you are using promises already so you won't need this
>>>> "magic".  Your API returns promises,  you are good to update to async/await
>>>> or generators.
>>>>
>>>> However, in the future you won't write promises directly if not as
>>>> returning values within some method .... right ?
>>>>
>>>> Looking at your code, I would always go for the second pattern instead
>>>> of the first one. So what if you'd like to use that already, simply adding
>>>> async and await and the only change to do in a well known/used
>>>> *synchronous* API would be to check if the returned value is held and
>>>> behave accordingly?
>>>>
>>>> That would give you a way to easily migrate to non-blocking as API
>>>> consumer, and an easy way as API author to update to a non blocking version
>>>> without breaking compatibility with other consumers.
>>>>
>>>> In this scenario,  you are still free to use `Promise.resolve(
>>>> fileGetContent("foo"))` which not on hold and not concretely
>>>> asynchronous in terms of `fileGetContent("foo")` operations, but as soon as
>>>> you go for async/await or a generator that function will return a Promise
>>>> for you.
>>>>
>>>> I hope it's clear now what is my idea.
>>>>
>>>> Regards
>>>>
>>>>
>>>>
>>>>
>>>> On Fri, Dec 4, 2015 at 6:41 AM, Claude Pache <claude.pache at gmail.com>
>>>> wrote:
>>>>
>>>>>
>>>>> Le 3 déc. 2015 à 22:07, Andrea Giammarchi <andrea.giammarchi at gmail.com>
>>>>> a écrit :
>>>>>
>>>>> Sorry I misread your code. Your case assumes fileGetContent always
>>>>> returns a Promise so my proposal won't be useful there because it's already
>>>>> used as Promise.
>>>>>
>>>>>
>>>>> You can remove that assumption by replacing `fileGetContent("foo")`
>>>>> with `Promise.resolve(fileGetContent("foo"))`.
>>>>>
>>>>>
>>>>> My idea is more about migrating to full async code without changing
>>>>> all the things around, giving an API the ability to behave differently.
>>>>>
>>>>>
>>>>> The key fact of my example is that I can (and do) write full async
>>>>> code without generators or async functions (just with ES3 + Promise), and
>>>>> you have no way to detect that.
>>>>> For example, the following code:
>>>>>
>>>>> ```js
>>>>> function bar() {
>>>>>     return Promise.resolve(fileGetContent("foo")).then(function (c) {
>>>>>         // whatever
>>>>>     })
>>>>> }
>>>>> ```
>>>>>
>>>>> is functionally equivalent to:
>>>>>
>>>>> ```js
>>>>> async function bar() {
>>>>>     const c = await fileGetContent("foo")
>>>>>     // whatever
>>>>> }
>>>>> ```
>>>>>
>>>>> In both cases, I can receive a value or a promise for a value, and in
>>>>> both cases getting a promise is strictly better.
>>>>> I don't want to be served an inferior version of `fileGetContent` in
>>>>> the first case just because you were unable to guess my intentions,
>>>>> and I won’t hurry to migrate my existing code to use the second
>>>>> pattern, because the difference is only cosmetic.
>>>>>
>>>>> —Claude
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Maybe it's too complicated or too magic to implement, that's OK anyway.
>>>>>
>>>>> On Thu, Dec 3, 2015 at 8:59 PM, Claude Pache <claude.pache at gmail.com>
>>>>> wrote:
>>>>>
>>>>>>
>>>>>> Le 3 déc. 2015 à 20:04, Andrea Giammarchi <
>>>>>> andrea.giammarchi at gmail.com> a écrit :
>>>>>>
>>>>>> I guess `held` would be like an arrow function, "transparent" when it
>>>>>> comes to held invokes (like context or arguments)
>>>>>>
>>>>>>
>>>>>> ? Sorry, but I don't understand how that would help to answer my
>>>>>> question.
>>>>>>
>>>>>> —Claude
>>>>>>
>>>>>>
>>>>>> On Thu, Dec 3, 2015 at 5:23 PM, Claude Pache <claude.pache at gmail.com>
>>>>>> wrote:
>>>>>>
>>>>>>> How would you detect that the following call to your
>>>>>>> `fileGetContent` function should return a Promise?
>>>>>>>
>>>>>>> ```js
>>>>>>> function oldSchool() {
>>>>>>>     return fileGetContent("foo").then(function (c) {
>>>>>>>         // ....
>>>>>>>     })
>>>>>>> }
>>>>>>> ```
>>>>>>>
>>>>>>> —Claude
>>>>>>>
>>>>>>>
>>>>>>> > Le 3 déc. 2015 à 13:15, Andrea Giammarchi <
>>>>>>> andrea.giammarchi at gmail.com> a écrit :
>>>>>>> >
>>>>>>> > Hi there,
>>>>>>> >   just writing down some thoughts about being able to understand
>>>>>>> if a method/function has been  executed within a generator/async and is
>>>>>>> being yielded/awaited.
>>>>>>> >
>>>>>>> > Rationale: API that would like to behave synchronously in some
>>>>>>> case, returning Promises in other cases.
>>>>>>> >
>>>>>>> > Example:
>>>>>>> >
>>>>>>> > ```js
>>>>>>> > function fileGetContent(fileName) {
>>>>>>> >   // random example
>>>>>>> >   if (held) {
>>>>>>> >     return fetch(fileName).then((r)=>r.text());
>>>>>>> >   } else {
>>>>>>> >     var xhr = new XMLHttpRequest;
>>>>>>> >     xhr.open('GET', fileName, false);
>>>>>>> >     xhr.send(null);
>>>>>>> >     return xhr.responseText;
>>>>>>> >   }
>>>>>>> > }
>>>>>>> > ```
>>>>>>> >
>>>>>>> > Above example will virtually return always the same type and it
>>>>>>> could work inside a generator or an  async function as long as it's being
>>>>>>> held.
>>>>>>> >
>>>>>>> > Does any of this make sense? Is it worth exploring this pattern?
>>>>>>> >
>>>>>>> > Thanks for any sort of thought.
>>>>>>> >
>>>>>>> > Best  Regards
>>>>>>> >
>>>>>>> >
>>>>>>> >
>>>>>>> >
>>>>>>> > _______________________________________________
>>>>>>> > es-discuss mailing list
>>>>>>> > es-discuss at mozilla.org
>>>>>>> > https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> es-discuss at mozilla.org
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151205/3e5be94d/attachment-0001.html>


More information about the es-discuss mailing list