more work on iterable promises, still not ready...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2022-06-02 12:05:37 +03:00
parent aa22c819ec
commit 3fada85cd9
2 changed files with 91 additions and 23 deletions

View File

@ -114,6 +114,11 @@ object.Constructor('IterablePromise', Promise, {
: [] }) },
// NOTE: this does not return an iterable promise as we can't know
// what the user reduces to...
// NOTE: the items can be handled out of order because the nested
// promises can resolve in any order.
// XXX write how to go around this...
// NOTE: since order of execution can not be guaranteed there is no
// point in implementing .reduceRight(..)
reduce: function(func, res){
return this.constructor(this.__list.flat(),
function(e){
@ -121,17 +126,6 @@ object.Constructor('IterablePromise', Promise, {
return [] })
.then(function(){
return res }) },
/*/ XXX this is wrong...
reduceRight: function(func, res){
return this.constructor(this.__list.flat().reverse(),
function(e){
res = func(res, e)
return [] })
.then(function(){
return res }) },
// XXX this is wrong...
reverse: function(){
return this.constructor(this.__list.flat().reverse()) },
flat: function(depth=1){
return this.constructor(this.__list.flat(),
function(e){
@ -142,11 +136,41 @@ object.Constructor('IterablePromise', Promise, {
: depth != 0 ?
e
: [e] }) },
// XXX REVERSE...
// XXX BUG:
// await Promise.iter([1, Promise.iter(['a', ['b', 'c']]), [2, 3], 4])
// .flat()
// -> [ 1, 'a', [ 'b', 'c' ], 2, 3, 4 ]
// await Promise.iter([1, Promise.iter(['a', ['b', 'c']]), [2, 3], 4])
// .flat()
// .reverse()
// -> [ 4, 2, 3, [ 'b', 'c', 'a' ], 1 ]
// ...should be:
// -> [ 4, 2, 3, [ 'b', 'c' ], 'a', 1 ]
// it's odd we are not seeing this in other places...
reverse: function(){
return this.constructor(this.__list
.map(function(elems){
return elems && elems.then ?
elems.then(function(res){
return res
.reverse()
.flat() })
: elems })
.reverse()
.flat()) },
// compatibility with root promise...
iter: function(){
return this.constructor(this.__list.flat()) },
//*/
return this.constructor(
// clone and unwrap the .__list
this.__list
.map(function(elems){
return elems && elems.then ?
elems.then(function(res){
return res.flat() })
: elems })
.flat()) },
// XXX do we need these?
// .pop()
@ -229,7 +253,13 @@ object.Constructor('IterablePromise', Promise, {
// manually handle the stop...
// - another issue here is that the stop would happen in order of
// execution and not order of elements...
// XXX add support for list as a promise....
__new__: function(_, list, handler){
// handle: IterablePromise(<list>, <mode>)
if(typeof(handler) == 'string'){
mode = handler
handler = undefined }
// instance...
var promise
var obj = Reflect.construct(
@ -246,12 +276,16 @@ object.Constructor('IterablePromise', Promise, {
if(promise){
// clone/normalize...
list = list
.map(function(e){
return (e && e.then) ?
e.then(function(e){
return [e] })
: [e] })
list =
list instanceof Promise ?
// XXX broken by reverse/flat but seems to work OK with others...
[list]
: list
.map(function(e){
return (e && e.then) ?
e.then(function(e){
return [e] })
: [e] })
if(handler){
// NOTE: this is recursive to handle expanding nested promises...
@ -262,7 +296,7 @@ object.Constructor('IterablePromise', Promise, {
return elems
.map(handle)
.flat() })
: elem
: elem
.map(handler)
.flat() }
@ -483,6 +517,10 @@ var PromiseProtoMixin =
module.PromiseProtoMixin =
object.Mixin('PromiseProtoMixin', 'soft', {
as: ProxyPromise,
// XXX
iter: function(){
return IterablePromise(this) },
})
PromiseProtoMixin(Promise.prototype)

View File

@ -70,6 +70,8 @@ Library of JavaScript type extensions, types and utilities.
- [`<promise-coop>.then(..)`](#promise-coopthen)
- [Promise iteration](#promise-iteration)
- [`Promise.iter(..)` / `promise.IterablePromise(..)`](#promiseiter--promiseiterablepromise)
- [`<promise>.iter()`](#promiseiter)
- [`<promise-iter>.iter()`](#promise-iteriter)
- [`<promise-iter>.map(..)` / `<promise-iter>.filter(..)` / `<promise-iter>.reduce(..)`](#promise-itermap--promise-iterfilter--promise-iterreduce)
- [`<promise-iter>.flat(..)`](#promise-iterflat)
- [`<promise-iter>.then(..)` / `<promise-iter>.catch(..)` / `<promise-iter>.finally(..)`](#promise-iterthen--promise-itercatch--promise-iterfinally)
@ -1452,8 +1454,8 @@ promise, and it is similar to a _generator_ in that it allows iteration over the
contained values and chaining of operations but unlike `Promise.all(..)` this
iteration occurs depth-first instead of breadth first.
Essentially one can think of _promise iterators_ vs. _generators_ as the former
being internally controlled and asynchronous while the later being externally
One can think of _promise iterators_ vs. _generators_ as the former being
internally controlled and asynchronous while the later being externally
controlled and synchronous.
Here is a traditional example using `Promise.all(..)`:
@ -1515,8 +1517,27 @@ XXX should we support infinite generators as input?
#### `Promise.iter(..)` / `promise.IterablePromise(..)`
Create an _iterable promise_
```bnf
Promise.iter(<array>)
Promise.iter(<promise>)
-> <promise-iter>
```
#### `<promise>.iter()`
```bnf
<promise>.iter()
-> <promise-iter>
```
#### `<promise-iter>.iter()`
Return a shallow copy of the current iterator.
```bnf
<promise-iter>.iter()
-> <promise-iter>
```
@ -1545,7 +1566,7 @@ and [`.reduce(..)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe
```bnf
<promise-iter>.reduce(<handler>, <state>)
-> <promise-iter>
-> <promise>
<handler>(<state>, <elem>)
-> <state>
@ -1558,6 +1579,15 @@ Note that these are different to `Array`'s equivalents in some details:
this is because the index with _out-of-order_ and _depth-first_ execution the
index is unknowable and the container is a promise/black-box.
This is especially critical for `.reduce(..)` as iteration in an order different
from the order of elements _can_ affect actual result if this is not expected.
`.reduce(..)` is also a bit different here in that it will return a basic
`<promise>` object as we can't know what will it will reduce to.
Note that since `.reduce(..)` order can not be guaranteed there is no point
in implementing `.reduceRigth(..)`.
#### `<promise-iter>.flat(..)`