From cc223ac0311247c574892014e3b7a62bbf04780e Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Tue, 17 Nov 2020 21:35:04 +0300 Subject: [PATCH] iterable promise seems to be ready... Signed-off-by: Alex A. Naanou --- Promise.js | 107 +++++++++++++++++++++++++++++++++++++++------------ package.json | 2 +- 2 files changed, 84 insertions(+), 25 deletions(-) diff --git a/Promise.js b/Promise.js index 0c94866..6aa112b 100644 --- a/Promise.js +++ b/Promise.js @@ -9,11 +9,13 @@ var object = require('ig-object') +//var {StopIteration} = require('./Array') + /*********************************************************************/ -// XXX does this need to be a distinct object??? +// XXX does this need to be a distinct object/constructor??? Promise.cooperative = function(){ var handlers return object.mixinFlat( @@ -47,36 +49,89 @@ var IterablePromise = module.IterablePromise = Promise.iter = object.Constructor('IterablePromise', Promise, { - // XXX + // XXX do we need this to be public??? __list: null, + // iterator methods... + // + // These will return a new IterablePromise instance... + // + // NOTE: these are different to Array's equivalents in that the handler + // is called not in the order of the elements but rather in order + // of promise resolution... + // NOTE: index of items is unknowable because items can expand on + // contract depending on handlrs (e.g. .filter(..) can remove + // items)... map: function(func){ - return IterablePromise(this.__list, function(e, i){ - return [func(e, i)] }) }, + return this.constructor(this.__list, function(e){ + return [func(e)] }) }, filter: function(func){ - return IterablePromise(this.__list, function(e, i){ - return func(e, i) ? + return this.constructor(this.__list, function(e){ + return func(e) ? [e] : [] }) }, - // XXX reduce: function(func, res){ - // XXX - }, + return this.constructor(this.__list, + function(e){ + res = func(res, e) + return [] }) + .then(function(){ + return res }) }, flat: function(depth=1){ - return IterablePromise(this.__list, function(e, i){ + return this.constructor(this.__list, function(e){ return (e && e.flat) ? e.flat(depth) : e }) }, - at: function(i){}, - slice: function(){}, - // XXX how does this support reduce??? - // handler(e, i) + // NOTE: these return a Promise instance... + then: function(handler){ + var that = this + return new Promise(function(resolve, reject){ + // then... + object.parentCall(IterablePromise.prototype.then, that, + function(){ + resolve(handler.call(this, ...arguments)) }) + that.catch(reject) }) }, + catch: function(handler){ + var that = this + return new Promise(function(resolve, reject){ + that.then(resolve) + // catch... + object.parentCall(IterablePromise.prototype.catch, that, + function(){ + reject(handler.call(this, ...arguments)) }) }) }, + finally: function(handler){ + var that = this + return new Promise(function(resolve, reject){ + // bind promise state to that... + that.then(resolve) + that.catch(reject) + // finally... + object.parentCall(IterablePromise.prototype.finally, that, + function(){ + handler.call(this, ...arguments) }) }) }, + + + // + // Promise.iter([ .. ]) + // -> iterable-promise + // + // Promise.iter([ .. ], handler) + // -> iterable-promise + // + // + // handler(e) // -> [value] // -> [] // - __new__: function(_, list, handler=false){ + // + // NOTE: element index is unknowable untill the full list is expanded + // as handler(..)'s return value can expand to any number of + // items... + // XXX we can make the index a promise, then if the client needs + // the value they can wait for it... + __new__: function(_, list, handler){ var promise // instance... @@ -90,12 +145,10 @@ object.Constructor('IterablePromise', Promise, { if(promise){ // apply handler(..) to the list... + // NOTE: the top level promises are not wrapped in arrays... // XXX should this be aborted on reject??? - // XXX we are keeping the top level promises unwrapped, is - // this correct??? - // ...needs testing.... - var c = 0 - list = obj.__list = + // ...need to be able to do a deep abort... + list = handler ? list.map(function(block){ return (block instanceof Array ? @@ -104,18 +157,24 @@ object.Constructor('IterablePromise', Promise, { .map(function(e){ // NOTE: we are counting actual expanded // values and not the "blocks"... - var i = ++c return (e && e.then && e.catch) ? // promise... e.then(function(v){ - return handler(v, i) }) + return handler(v) }) // basic value... - : handler(e, i) }) }) + : handler(e) }) }) .flat() - : list.map(function(e){ + : handler === undefined ? + list.map(function(e){ return e instanceof Promise ? e : [e] }) + : list.slice() + + Object.defineProperty(obj, '__list', { + value: list, + enumerable: false, + }) // handle promise state... Promise.all(list) diff --git a/package.json b/package.json index 6f8979e..182ea3c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ig-types", - "version": "3.7.7", + "version": "3.7.8", "description": "Generic JavaScript types and type extensions...", "main": "main.js", "scripts": {