From 600d18650968ca184a53d608092581d91cf1586b Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Wed, 11 Jan 2023 12:09:21 +0300 Subject: [PATCH] refactoring... Signed-off-by: Alex A. Naanou --- Promise.js | 310 +++++++++++++++++++++++++++-------------------------- 1 file changed, 156 insertions(+), 154 deletions(-) diff --git a/Promise.js b/Promise.js index 2da7c00..3ce38c1 100644 --- a/Promise.js +++ b/Promise.js @@ -37,166 +37,168 @@ var generator = require('./generator') //--------------------------------------------------------------------- // XXX EXPERIMENTING... +// packed format API... // -// pack() -// pack() -// -> -// -// ::= -// -// | -// -// ::= -// [ -// -// | - array -// | -// | , -// ... -// ] -// -// NOTE: when all promises are expanded the packed array can be unpacked -// by simply calling .flat() -// -// XXX see if we can self-expand promises -- promise replaces self when -// resolved -- this would solve the issue with promises accumulating -// issue but would add complexity... -// ...to reduce complexity make this a separate function running -// both in in-place mutate mode as well as a callback getting a -// copy... -// XXX migrate these back into InteractivePromise... -// XXX does this need onerror(..) ??? -var pack = -module.pack = -function(list){ - // promise list... - if(list instanceof Promise){ - return list.then(pack) } - // async promise list... - if(typeof(list) == 'object' - && Symbol.asyncIterator in list){ +var packed = +module.packed = +{ + // + // pack() + // pack() + // -> + // + // ::= + // + // | + // + // ::= + // [ + // + // | - array + // | + // | , + // ... + // ] + // + // NOTE: when all promises are expanded the packed array can be unpacked + // by simply calling .flat() + // + // XXX see if we can self-expand promises -- promise replaces self when + // resolved -- this would solve the issue with promises accumulating + // issue but would add complexity... + // ...to reduce complexity make this a separate function running + // both in in-place mutate mode as well as a callback getting a + // copy... + // XXX migrate these back into InteractivePromise... + // XXX does this need onerror(..) ??? + pack: function(list){ + var that = this + // promise list... + if(list instanceof Promise){ + return list.then(this.pack.bind(this)) } + // async promise list... + if(typeof(list) == 'object' + && Symbol.asyncIterator in list){ + return list + .then(function(list){ + return that.pack(list) }) } + // generator list... (XXX do a better test...) + if(typeof(list) == 'object' + && !list.map + && Symbol.iterator in list){ + list = [...list] } + // array... return list - .then(function(list){ - return pack(list) }) } - // generator list... (XXX do a better test...) - if(typeof(list) == 'object' - && !list.map - && Symbol.iterator in list){ - list = [...list] } - // array... - return list - .map(function(elem){ - return elem instanceof Array ? - [elem] - : elem instanceof Promise ? - elem.then(function(elem){ - return elem instanceof Array ? - [elem] - : elem }) - : elem }) } + .map(function(elem){ + return elem instanceof Array ? + [elem] + : elem instanceof Promise ? + elem.then(function(elem){ + return elem instanceof Array ? + [elem] + : elem }) + : elem }) }, -// -// handle(, [, ]) -// -> -// -// XXX revise nested promise handling... -// ...something like simplify() -> ??? -var handle = -module.handle = -function(list, handler, onerror){ - var handlers = [...arguments].slice(1) + // + // handle(, [, ]) + // -> + // + // XXX revise nested promise handling... + // ...something like simplify() -> ??? + handle: function(packed, handler, onerror){ + var that = this + var handlers = [...arguments].slice(1) - if(list instanceof Promise){ - return list.then(function(list){ - return handle(list, ...handlers) }) } + if(packed instanceof Promise){ + return packed.then(function(packed){ + return that.handle(packed, ...handlers) }) } - var map = Array.STOP ? - 'smap' - : 'map' - return list - // NOTE: we do not need to rapack after this because the handlers - // will get the correct (unpacked) values and it's their - // responsibility to pack them if needed... - .flat() - [map]( - function(elem){ - return elem instanceof Promise ? - elem.then(function(elem){ - var has_promise = false - var res = - elem instanceof Array ? - // un-.flat()-end arrays in promise... - // NOTE: do the same thing handle(..) does - // but on a single level, without expanding - // arrays... - elem.map(function(elem){ - var res = elem instanceof Promise ? - elem.then(handler) - : handler(elem) - has_promise = has_promise - || res instanceof Promise - return res }) - // other... - : handler(elem) - // compensate for the outer .flat()... - return (has_promise - && res instanceof Array) ? - // NOTE: since we are already in a promise - // grouping things here is not a big - // deal (XXX ???), however this is needed - // to link nested promises with the - // containing promise... - // XXX .all(..) will resolve after all the - // contents are resolved, while returning - // res.flat() will allow access to all the - // values including the individual promises - // can we combine the two??? - // ...can we split this up into promises and - // other values and Promise.all(..) only - // the promises??? - //res.flat() - Promise.all(res) - .then(function(res){ - return res.flat() }) - : res instanceof Array ? - res.flat() - : res }) - : handler(elem) }, - // onerror... - ...handlers.slice(1)) } + var map = Array.STOP ? + 'smap' + : 'map' + return packed + // NOTE: we do not need to rapack after this because the handlers + // will get the correct (unpacked) values and it's their + // responsibility to pack them if needed... + .flat() + [map]( + function(elem){ + return elem instanceof Promise ? + elem.then(function(elem){ + var has_promise = false + var res = + elem instanceof Array ? + // un-.flat()-end arrays in promise... + // NOTE: do the same thing handle(..) does + // but on a single level, without expanding + // arrays... + elem.map(function(elem){ + var res = elem instanceof Promise ? + elem.then(handler) + : handler(elem) + has_promise = has_promise + || res instanceof Promise + return res }) + // other... + : handler(elem) + // compensate for the outer .flat()... + return (has_promise + && res instanceof Array) ? + // NOTE: since we are already in a promise + // grouping things here is not a big + // deal (XXX ???), however this is needed + // to link nested promises with the + // containing promise... + // XXX .all(..) will resolve after all the + // contents are resolved, while returning + // res.flat() will allow access to all the + // values including the individual promises + // can we combine the two??? + // ...can we split this up into promises and + // other values and Promise.all(..) only + // the promises??? + //res.flat() + Promise.all(res) + .then(function(res){ + return res.flat() }) + : res instanceof Array ? + res.flat() + : res }) + : handler(elem) }, + // onerror... + ...handlers.slice(1)) }, -// -// unpack() -// -> -// -var unpack = -module.unpack = -function(list){ - if(list instanceof Promise){ - return list.then(unpack) } - var input = list - // NOTE: we expand promises on the first two levels of the packed - // list and then flatten the result... - for(var [i, elem] of Object.entries(list)){ - // expand promises in lists... - if(elem instanceof Array){ - for(var e of elem){ - if(e instanceof Promise){ - // copy the input (on demand) list as we'll need to - // modify it... - list === input - && (list = list.slice()) - // NOTE: this will immediately be caught by the - // Promise condition below... - elem = list[i] = - Promise.all(elem) - break } } } - // expand promises... - if(elem instanceof Promise){ - return Promise.all(list) - .then(unpack) } } - // the list is expanded here... - return list.flat() } + // + // unpack() + // -> + // + unpack: function(packed){ + if(packed instanceof Promise){ + return packed.then(this.unpack.bind(this)) } + var input = packed + // NOTE: we expand promises on the first two levels of the packed + // list and then flatten the result... + for(var [i, elem] of Object.entries(packed)){ + // expand promises in lists... + if(elem instanceof Array){ + for(var e of elem){ + if(e instanceof Promise){ + // copy the input (on demand) list as we'll need to + // modify it... + packed === input + && (packed = packed.slice()) + // NOTE: this will immediately be caught by the + // Promise condition below... + elem = packed[i] = + Promise.all(elem) + break } } } + // expand promises... + if(elem instanceof Promise){ + return Promise.all(packed) + .then(this.unpack.bind(this)) } } + // the list is expanded here... + return packed.flat() }, +} // // itemResolved(, [, ])