reworking promise iteration, still one pesky issue to iron out (see code). + working on testing...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2022-06-06 12:29:13 +03:00
parent f209824445
commit a7ea5014be
4 changed files with 205 additions and 76 deletions

View File

@ -95,16 +95,31 @@ object.Constructor('IterablePromise', Promise, {
// .some(..) / .every(..)
// .sort(..)
//
// XXX sould these support returning a promise???
// XXX should these support STOP???
map: function(func){
return this.constructor(this,
function(e){
return [func(e)] }) },
//return [func(e)] }) },
var res = func(e)
return res instanceof Promise ?
res.then(function(e){
return [e] })
: [res] }) },
filter: function(func){
return this.constructor(this,
function(e){
return func(e) ?
[e]
//return func(e) ?
// [e]
// : [] }) },
var res = func(e)
return res instanceof Promise ?
res.then(function(res){
return res ?
[e]
: [] })
: res ?
[e]
: [] }) },
// NOTE: this does not return an iterable promise as we can't know
// what the user reduces to...
@ -114,6 +129,7 @@ object.Constructor('IterablePromise', Promise, {
// XXX write how to go around this...
// NOTE: since order of execution can not be guaranteed there is no
// point in implementing .reduceRight(..)
// XXX should func be able to return a promise???
reduce: function(func, res){
return this.constructor(this,
function(e){
@ -268,6 +284,14 @@ 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 BUG:
// await Promise.iter([1,Promise.resolve(2),[3]])
// is not the same as:
// await Promise.iter([1,Promise.resolve(2),[3]])
// .map(e => Promise.resolve(e))
// ...again the problem is in the normalized input...
// XXX BUG: .map(..) returning a promise broken again...
__new__: function(_, list, handler){
// instance...
var promise
@ -287,17 +311,43 @@ object.Constructor('IterablePromise', Promise, {
if(handler != 'raw'){
handler = handler
?? function(e){
return [e] }
?? function(e){ return [e] }
// NOTE: this is recursive to handle expanding nested promises...
var handle = function(elem){
// call the handler...
return (elem && elem.then) ?
//elem.then(function(elem){
// return handler(elem) })
elem.then(handler)
: handler(elem) }
// NOTE: these are nor exactly the same, but it would be
// nice to figure out a way to merge thess (XXX)
// XXX BUG: this seems to for some reason cack promises returned
// by .map(..) / .. into arrays...
// await Promise.iter([1, Promise.resolve(2), [3]])
// .map(e => Promise.resolve(e))
// ...will return a list with three promises...
// the odd thing is that printing the items shows
// that this gets the resolved results so it might
// seem that the problem is a tad bigger...
// ...also, the promises in the list are correct,
// seems that we need to .flat(..) the list...
var handleNormList = function(list){
return list.map(function(sub){
// XXX this get's the already resolved values...
//console.log('---', sub)
return sub instanceof Promise ?
sub.then(function(sub){
return sub
.map(handle)
.flat() })
: sub
.map(handle)
.flat() }) }
var handleList = function(list){
return list instanceof Promise ?
list.then(function(list){
return [list].flat()
.map(handle) })
: [list].flat()
.map(handle) }
// handle the list...
// NOTE: we can't .flat() the results here as we need to
@ -307,24 +357,8 @@ object.Constructor('IterablePromise', Promise, {
&& !(list.__list instanceof Promise)) ?
// NOTE: this is essentially the same as below but
// with a normalized list as input...
// XXX can we merge the two???
list.__list
.map(function(elems){
return elems instanceof Promise ?
elems.then(function(elems){
return elems
.map(handle)
.flat() })
: elems
.map(handle)
.flat() })
: list instanceof Promise ?
// special case: promised list...
list.then(function(list){
return [list].flat()
.map(handle) })
: [list].flat()
.map(handle) }
handleNormList(list.__list)
: handleList(list) }
Object.defineProperty(obj, '__list', {
value: list,
@ -337,9 +371,7 @@ object.Constructor('IterablePromise', Promise, {
list
: Promise.all([list].flat()))
.then(function(res){
promise.resolve(handler ?
res.flat()
: res) })
promise.resolve(res.flat()) })
.catch(promise.reject) }
return obj },

36
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "ig-types",
"version": "6.11.0",
"version": "6.13.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "ig-types",
"version": "6.11.0",
"version": "6.13.0",
"license": "BSD-3-Clause",
"dependencies": {
"ig-object": "^5.4.16",
@ -341,15 +341,15 @@
"integrity": "sha512-5MAUWSwfHKQNrgLroXxBHjlhrhVbhzlVqvUcfMDjUeK/ufWQ9THE0HDcvhfu+YrPfRjTR2QpD2Ygp+2H4O0C6g=="
},
"node_modules/ig-test": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/ig-test/-/ig-test-1.4.8.tgz",
"integrity": "sha512-TwSVA/874sHTc05RE+HtMW1BEbgws868CTQzpBwnVMYTKj6Th0mrNSls9SsTM/Ias2giPRZfusg+U/vc/JIcQQ==",
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/ig-test/-/ig-test-1.5.4.tgz",
"integrity": "sha512-1N2U3v6tSPGUeBNnCuFWem09ngNkuMT1NGEEyVtA73VR5nz8GMbroifiPX0+j/GLqBJ/u39bsMCdZSMaIMTRdg==",
"dev": true,
"dependencies": {
"colors": "^1.4.0",
"colors": "1.4.0",
"glob": "^7.1.6",
"ig-argv": "^2.13.2",
"ig-object": "^5.2.6"
"ig-argv": "^2.16.3",
"ig-object": "^5.4.16"
},
"bin": {
"runtests": "test.js"
@ -478,7 +478,7 @@
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"dependencies": {
"wrappy": "1"
@ -526,7 +526,7 @@
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
@ -1041,15 +1041,15 @@
"integrity": "sha512-5MAUWSwfHKQNrgLroXxBHjlhrhVbhzlVqvUcfMDjUeK/ufWQ9THE0HDcvhfu+YrPfRjTR2QpD2Ygp+2H4O0C6g=="
},
"ig-test": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/ig-test/-/ig-test-1.4.8.tgz",
"integrity": "sha512-TwSVA/874sHTc05RE+HtMW1BEbgws868CTQzpBwnVMYTKj6Th0mrNSls9SsTM/Ias2giPRZfusg+U/vc/JIcQQ==",
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/ig-test/-/ig-test-1.5.4.tgz",
"integrity": "sha512-1N2U3v6tSPGUeBNnCuFWem09ngNkuMT1NGEEyVtA73VR5nz8GMbroifiPX0+j/GLqBJ/u39bsMCdZSMaIMTRdg==",
"dev": true,
"requires": {
"colors": "^1.4.0",
"colors": "1.4.0",
"glob": "^7.1.6",
"ig-argv": "^2.13.2",
"ig-object": "^5.2.6"
"ig-argv": "^2.16.3",
"ig-object": "^5.4.16"
}
},
"inflight": {
@ -1148,7 +1148,7 @@
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"requires": {
"wrappy": "1"
@ -1181,7 +1181,7 @@
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"dev": true
},
"path-key": {

View File

@ -1,6 +1,6 @@
{
"name": "ig-types",
"version": "6.12.1",
"version": "6.13.1",
"description": "Generic JavaScript types and type extensions...",
"main": "main.js",
"scripts": {

151
test.js
View File

@ -111,45 +111,142 @@ var cases = test.Cases({
RegExp: function(assert){
},
Promise: function(assert){
IterablePromise: test.TestSet(function(){
var create = function(assert, value){
return {
input: value,
output: assert(Promise.iter(value), 'Promise.iter(', value, ')'),
} }
this.Setup({
empty: function(assert){
return create(assert, []) },
value: function(assert){
return create(assert, 123) },
array: function(assert){
return create(assert, [1, 2, 3]) },
nested_array: function(assert){
return create(assert, [1, 2, [3]]) },
promise_value: function(assert){
return create(assert, Promise.resolve(123)) },
promise_array: function(assert){
return create(assert, Promise.resolve([1, 2, 3])) },
promise_nested_array: function(assert){
return create(assert, Promise.resolve([1, 2, [3]])) },
array_mixed: function(assert){
return create(assert, [1, Promise.resolve(2), 3]) },
nested_array_mixed: function(assert){
return create(assert, [
1,
Promise.resolve(2),
[3],
Promise.resolve([4]),
]) },
promise_array_mixed: function(assert){
return create(assert, Promise.resolve([1, Promise.resolve(2), 3])) },
promise_nested_array_mixed: function(assert){
return create(assert, Promise.resolve([
1,
Promise.resolve(2),
[3],
Promise.resolve([4]),
])) },
})
this.Modifier({
nest: function(assert, setup){
setup.output = Promise.iter(setup.output)
return setup },
iter: function(assert, setup){
setup.output = setup.output.iter()
return setup },
map_asis: function(assert, setup){
setup.output = setup.output
.map(function(e){
return e })
return setup },
map_promise: function(assert, setup){
setup.output = setup.output
.map(function(e){
return Promise.resolve(e) })
return setup },
filter_all: function(assert, setup){
setup.output = setup.output
.filter(function(e){ return true })
return setup },
// XXX either the test is worng or something is broken...
filter_none: function(assert, setup){
return {
input: [],
output: setup.output
.filter(function(e){ return false }),
} },
})
this.Test({
value: async function(assert, {input, output}){
var res = await output
assert(res instanceof Array, 'result is array')
input instanceof Array ?
assert.array(res,
await Promise.all(input),
'array -> array')
: (input instanceof Promise && await input instanceof Array) ?
assert.array(res,
await input,
'promise array -> array')
: input instanceof Promise ?
assert.array(res,
[await input],
'promise value -> array')
: assert.array(res,
[input],
'value -> array') },
})
}),
Promise: async function(assert){
var p = assert(Promise.cooperative(), '.cooperative()')
//var p = assert(promise._CooperativePromise())
assert(!p.isSet, '.isSet is false')
assert(!p.isSet, 'promise unset')
var RESOLVE = 123
var then = false
var done = false
var then
p.then(function(v){
// XXX this does not get printed for some reason...
console.log('!!!!!!!!!!! then')
// XXX this seems not to work/print/count a fail...
assert(false, 'test fail')
then = assert(v == RESOLVE, '.then(..) handled') })
then = v })
assert(!p.isSet, '.isSet is false')
var fin
p.finally(function(){
fin = true })
done = assert(true, '.finally(..) handled') })
assert(!p.isSet, '.isSet is false')
assert(!p.isSet, 'promise unset')
p.set(RESOLVE)
assert(p.isSet, '.isSet')
assert(p.isSet, 'promise set')
// XXX without setTimeout(..) these are run before the
// .then(..) / .finally(..) have a chance to run...
// ...not yet sure how I feel about this...
// XXX with setTimeout(..) these appear not to have ANY effect,
// as if setTimeout(..) did not run...
setTimeout(function(){
assert(false, 'test fail')
assert(then == RESOLVE, '.then(..)')
assert(fin, '.finally(..)')
}, 0)
// allow the promise to finalize...
await p
assert(then, '.then(..): confirmed')
assert(done, '.done(..): confirmed')
// XXX
assert(await Promise.iter([1, Promise.resolve(2), [3]]), '.iter(..)')
assert.array(
await Promise.iter([1, 2, 3]),
[1, 2, 3],
'basic array')
assert.array(
await Promise.iter([1, Promise.resolve(2), 3]),
[1, 2, 3],
'promises as elements')
},
// Date.js