Reflection to know if executed within a generator/async ?

Andrea Giammarchi andrea.giammarchi at gmail.com
Fri Dec 4 17:31:28 UTC 2015


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/20151204/071ecce3/attachment-0001.html>


More information about the es-discuss mailing list