> let later;
> export default {then(notify) { if (ready) notify(later); else
queue(notify); }}how's that different from a Promise ? Don't get me wrong, I have a module [1] that does that already (use a symbol as key and that's it) but yet for an importer, if that has to be handled like a Promise, then why not just a Promise ? This is the bit I don't get. Thanks [1] https://github.com/WebReflection/broadcast#broadcast-- On Fri, Apr 21, 2017 at 7:38 PM, Bradley Meck <[email protected]> wrote: > > how asynchronous export helps here ? > > >>> I cannot think about a single use case for wanting that: it's not > usable from within the module, it won't be usable outside unless checked > via ... an interval ? > > As stated in previous email: > > >> The previous email was stating there are use cases for updating > exports. > > If you are updating exports that in general means live bindings / > asynchronous work. > > > already covered by `export default new Promise(async () => {})` , right > ? > > Kind of, this sacrifices live binding since `default` can only ever have 1 > value. Something could use a thenable to export multiple values over time > however similar to a live binding: > > ``` > let later; > export default {then(notify) { if (ready) notify(later); else > queue(notify); }} > ``` > > > how is the module consumer supposed to know when these exports are > ready? > > > if it's an event emitted, libraries trusting the event that already > happened will never know, so we are back to polling, which is a very bad > approach, IMO, and if the solution is a Promise then it's covered already. > > Please read my previous email: > > >> The answer is no pattern has been standardized so it depends on your > proposed solution. A `then()`-able is already in spec and seems like a > possible choice (though I wouldn't use a Promise); top level await could be > another but blocks the module graph. TDZ poll/checking on imports could be > another (though not-preferable) solution. I am sure we could bikeshed other > approaches. > > > so if two importers happen at different times the second importer can > compromise with undesired features the first one or vice-verssa? > > No, ESM modules are only evaluated once. Such checks are most likely done > up front. However, enabling a debugger for example might cause a new set of > exports to be loaded/exported. > > > So, like I've said, I don't see real-world scenarios for exported > modules that changes without notice. > It looks unpractical and undesired. > > As stated in previous email: > > > Exporting asynchronously doesn't provide any coordination point ... > > The rest of my email(s) have been talking about coordination. > > On Fri, Apr 21, 2017 at 1:28 PM, Andrea Giammarchi < > [email protected]> wrote: > >> > It could be something that is being mocked/spied upon. >> >> how asynchronous export helps here ? >> >> >> >> > It could be part of a circular dependency and so the modules do get a >> hold of eachother without finishing evaluation. >> >> already covered by `export default new Promise(async () => {})` , right ? >> >> >> >> > It could be that it lazily/async populates its exports due to costs. >> >> how is the module consumer supposed to know when these exports are ready? >> >> if it's an event emitted, libraries trusting the event that already >> happened will never know, so we are back to polling, which is a very bad >> approach, IMO, and if the solution is a Promise then it's covered already. >> >> >> >> > It could be that it is relying upon context to determine if something >> should be exported (debug flag etc.) >> >> so if two importers happen at different times the second importer can >> compromise with undesired features the first one or vice-verssa? >> >> Dynamic exports are possible since ever on CommonJS world (same as >> imports) and I've truly rarely seen the need to lazy export or lazy import. >> Conditional import yes, and conditional exports too but never at distance. >> >> So, like I've said, I don't see real-world scenarios for exported modules >> that changes without notice. >> It looks unpractical and undesired. >> >> Can you point at me at a single module that needs to do that? >> Maybe I'm missing something. >> >> Thanks >> >> >> >> >> On Fri, Apr 21, 2017 at 7:18 PM, Bradley Meck <[email protected]> >> wrote: >> >>> > Let me ask again: as a module consumer, how are you supposed to know >>> when an export is available? >>> >>> The previous email was stating there are use cases for updating exports. >>> >>> The answer is no pattern has been standardized so it depends on your >>> proposed solution. A `then()`-able is already in spec and seems like a >>> possible choice (though I wouldn't use a Promise); top level await could be >>> another but blocks the module graph. TDZ poll/checking on imports could be >>> another (though not-preferable) solution. I am sure we could bikeshed other >>> approaches. >>> >>> I don't see "None of these haven't been solved already through better >>> pattern." as a response to all the use cases I described. >>> >>> On Fri, Apr 21, 2017 at 1:13 PM, Andrea Giammarchi < >>> [email protected]> wrote: >>> >>>> None of these haven't been solved already through better pattern. >>>> >>>> Let me ask again: as a module consumer, how are you supposed to know >>>> when an export is available? >>>> >>>> On Fri, Apr 21, 2017 at 7:08 PM, Bradley Meck <[email protected]> >>>> wrote: >>>> >>>>> Could be several reasons, it could be exporting a counter/log that >>>>> changes over time. >>>>> >>>>> It could be something that is being mocked/spied upon. >>>>> >>>>> It could be part of a circular dependency and so the modules do get a >>>>> hold of eachother without finishing evaluation. >>>>> >>>>> It could be that it lazily/async populates its exports due to costs. >>>>> >>>>> It could be that it is relying upon context to determine if something >>>>> should be exported (debug flag etc.) >>>>> >>>>> Probably plenty more reasons. >>>>> >>>>> On Fri, Apr 21, 2017 at 11:58 AM, Andrea Giammarchi < >>>>> [email protected]> wrote: >>>>> >>>>>> > a Promise cannot change value over time, unlike a live binding. >>>>>> >>>>>> when is a module that changes values and without any notification >>>>>> desirable? >>>>>> >>>>>> I cannot think about a single use case for wanting that: it's not >>>>>> usable from within the module, it won't be usable outside unless checked >>>>>> via ... an interval ? >>>>>> >>>>>> The main point here is that asynchronous import might also inevitably >>>>>> mean asynchronous exports. >>>>>> >>>>>> Early access to unusable modules doesn't seem a real-world solution >>>>>> to me. >>>>>> >>>>>> What am I missing? >>>>>> >>>>>> Best Regards >>>>>> >>>>>> >>>>>> >>>>>> On Fri, Apr 21, 2017 at 5:48 PM, Bradley Meck <[email protected] >>>>>> > wrote: >>>>>> >>>>>>> I have been thinking about this some, I do think there is something >>>>>>> here, but am not sure it warrants any changes. Exporting asynchronously >>>>>>> doesn't provide any coordination point so the general idea is to export >>>>>>> a >>>>>>> Promise, but a Promise cannot change value over time, unlike a live >>>>>>> binding. So, a more appropriate way might be to export a "ready" binding >>>>>>> that is a Promise. Without some kind of async coordination like a >>>>>>> `.then()`-able you would also suffer from `undefined` being a possible >>>>>>> initialized and uninitialized value. >>>>>>> >>>>>>> ``` >>>>>>> let later; >>>>>>> export {later}; >>>>>>> export const ready = someAsyncWork().then(v => later = v); >>>>>>> ``` >>>>>>> >>>>>>> This does still mean that `later` can be accessed before it is >>>>>>> ready, in my opinion somewhat against the idea of a TDZ wanting to wait >>>>>>> for >>>>>>> access to be ready. >>>>>>> >>>>>>> I would be interested in something like: >>>>>>> >>>>>>> ``` >>>>>>> async let later; >>>>>>> export {later}; >>>>>>> export const ready = someAsyncWork().then(v => later = v); >>>>>>> ``` >>>>>>> >>>>>>> That preserves the TDZ until assignment. Or, something that wraps >>>>>>> `later` in a non-promise `.then()`-able that `import` understands and >>>>>>> can >>>>>>> unwrap to a live binding. >>>>>>> >>>>>>> All of that said, I am not sure this specific of a use warrants >>>>>>> language changes as I can think of problems with the ideas I have >>>>>>> proposed >>>>>>> as well. >>>>>>> >>>>>>> On Fri, Apr 21, 2017 at 11:24 AM, Benoit Marchant <[email protected]> >>>>>>> wrote: >>>>>>> >>>>>>>> I really like that idea >>>>>>>> >>>>>>>> On Apr 21, 2017, at 08:22, Andrea Giammarchi < >>>>>>>> [email protected]> wrote: >>>>>>>> >>>>>>>> nobody has any thought on this ? >>>>>>>> >>>>>>>> Maybe the following pattern would be just about enough to solve a >>>>>>>> generic asynchronous import/export ? >>>>>>>> >>>>>>>> ```js >>>>>>>> export default new Promise(async $export => { >>>>>>>> >>>>>>>> const utils = await import('./utils.js').default; >>>>>>>> >>>>>>>> $export({module: 'asynchronous', utils}); >>>>>>>> >>>>>>>> }); >>>>>>>> ``` >>>>>>>> >>>>>>>> Best Regards >>>>>>>> >>>>>>>> On Thu, Apr 20, 2017 at 11:51 AM, Andrea Giammarchi < >>>>>>>> [email protected]> wrote: >>>>>>>> >>>>>>>>> Even if unpolyfillable through simple `function import() {}` >>>>>>>>> declaration, >>>>>>>>> I've managed to create a polyfill/payground for the ESnext's >>>>>>>>> dynamic import() [1] >>>>>>>>> >>>>>>>>> This also made me wonder if there's any plan to provide a way to >>>>>>>>> asynchronously >>>>>>>>> export modules that depends on those that use asynchronous import. >>>>>>>>> >>>>>>>>> Since AFAIK modules have no top-level await, the only pattern I >>>>>>>>> can see right now >>>>>>>>> to import something asynchronous is the following one: >>>>>>>>> >>>>>>>>> ```js >>>>>>>>> // module ./js/c.js >>>>>>>>> export default Promise.all([ >>>>>>>>> import('./js/a.js'), >>>>>>>>> import('./js/a.js') >>>>>>>>> ]).then([a, b] => { >>>>>>>>> const module = {a, b, c() {}}; >>>>>>>>> return module; >>>>>>>>> }); >>>>>>>>> >>>>>>>>> // module that uses ./js/c.js >>>>>>>>> import('./js/c.js').then(m => m.default).then(c => { >>>>>>>>> c.a(); c.b(); c.c(); >>>>>>>>> }); >>>>>>>>> ``` >>>>>>>>> >>>>>>>>> However, above boilerplate doesn't seem ideal compared with >>>>>>>>> something like the following: >>>>>>>>> >>>>>>>>> ```js >>>>>>>>> // module ./js/c.js >>>>>>>>> export default await Promise.all([ >>>>>>>>> import('./js/a.js'), >>>>>>>>> import('./js/a.js') >>>>>>>>> ]).then([a, b] => { >>>>>>>>> const module = {a, b, c() {}}; >>>>>>>>> return module; >>>>>>>>> }); >>>>>>>>> >>>>>>>>> // module that uses ./js/c.js >>>>>>>>> import * as c from './js/c.js'; >>>>>>>>> ``` >>>>>>>>> >>>>>>>>> But again, AFAIK that's not possible. >>>>>>>>> >>>>>>>>> The clear advantage is that the module consumer wouldn't need to >>>>>>>>> know, or care, >>>>>>>>> if the loaded module depends on some dynamic, asynchronous, import, >>>>>>>>> meaning modules can be updated and eventually moved to async >>>>>>>>> transparently >>>>>>>>> for any module consumer. >>>>>>>>> >>>>>>>>> As summary, is any solution worth exploring/improving/fixing/pla >>>>>>>>> nning? >>>>>>>>> >>>>>>>>> Thank you. >>>>>>>>> Best Regards >>>>>>>>> >>>>>>>>> [1] https://github.com/WebReflection/import.js#importjs >>>>>>>>> >>>>>>>> >>>>>>>> _______________________________________________ >>>>>>>> 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

