From 6e68d08b0677d39b956cad4eb081ea8c6abc5e99 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Thu, 5 Nov 2020 16:40:41 +0300 Subject: [PATCH] added StopIteration support to chunk iteration... Signed-off-by: Alex A. Naanou --- Array.js | 63 ++++++++++++++++++++++++++++++++++++++++++---------- Promise.js | 10 +++++++-- package.json | 2 +- test.js | 54 +++++++++++++++++++++++++++++++++++++------- 4 files changed, 106 insertions(+), 23 deletions(-) diff --git a/Array.js b/Array.js index 35a005a..f0ede2a 100644 --- a/Array.js +++ b/Array.js @@ -11,14 +11,29 @@ (function(require){ var module={} // make module AMD/node compatible... /*********************************************************************/ +var object = require('ig-object') /*********************************************************************/ +var StopIteration = +module.StopIteration = + object.Constructor('StopIteration', Error, { + // NOTE: I do not get why JavaScript's Error implements this + // statically... + get name(){ + return this.constructor.name }, + // NOTE: msg is handled by Error(..) + __init__: function(msg){ + this.msg = msg }, + }) + +//--------------------------------------------------------------------- + // Array.prototype.flat polyfill... // // NOTE: .flat(..) is not yet supported in IE/Edge... @@ -201,6 +216,10 @@ Array.prototype.inplaceSortAs = function(other){ // 20 - chunk size // '20' - chunk size // '20C' - number of chunks +// +// +// StopIteration can be thrown in func or chunk_handler at any time to +// abort iteration, this will reject the promise. // // // The main goal of this is to not block the runtime while processing a @@ -231,10 +250,20 @@ var makeChunkIter = function(iter, wrapper){ // special case... // no need to setTimeout(..) if smaller than size... if(this.length <= size){ - var res = this[iter](func, ...rest) - postChunk - && postChunk.call(this, this, res, 0) - return Promise.all(res) } + try { + // handle iteration... + var res = this[iter](func, ...rest) + // handle chunk... + postChunk + && postChunk.call(this, this, res, 0) + return Promise.all(res) + // handle StopIteration... + } catch(err){ + if(err === StopIteration){ + return Promise.reject() + } else if( err instanceof StopIteration){ + return Promise.reject(err.msg) } + throw err } } var res = [] var _wrapper = wrapper.bind(this, res, func, this) @@ -243,14 +272,24 @@ var makeChunkIter = function(iter, wrapper){ var next = function(chunks){ setTimeout(function(){ var chunk, val - res.push( - val = (chunk = chunks.shift())[iter](_wrapper, ...rest)) - // handle chunk... - postChunk - && postChunk.call(that, - chunk.map(function([i, v]){ return v }), - val, - chunk[0][0]) + try { + // handle iteration... + res.push( + val = (chunk = chunks.shift())[iter](_wrapper, ...rest)) + // handle chunk... + postChunk + && postChunk.call(that, + chunk.map(function([i, v]){ return v }), + val, + chunk[0][0]) + // handle StopIteration... + } catch(err){ + if(err === StopIteration){ + return reject() + } else if( err instanceof StopIteration){ + return reject(err.msg) } + throw err } + // stop condition... chunks.length == 0 ? resolve(res.flat(2)) diff --git a/Promise.js b/Promise.js index ba9ff57..70b51b6 100644 --- a/Promise.js +++ b/Promise.js @@ -45,12 +45,17 @@ object.Constructor('CooperativePromise', Promise, { methods.resolve = resolve methods.reject = reject if(func){ + // XXX this can fullfill the promise -- need to keep + // things consistent... return func.call(this, ...arguments) } } ], CooperativePromise) /*/ if we are fulfilled before being set, we are set :) // XXX for some reason this breaks either .__new__(..) if called // outside of setTimeout(..) or hangs the promise on resolve // if inside... + // ...the same thing happens if we call .then(..)/.catch(..) + // The odd thing is that calling .finally(..) later works OK... + // ...increasing the timeout just delays the hang... setTimeout(function(){ obj.finally(function(){ delete obj.__resolve @@ -74,7 +79,8 @@ object.Constructor('CooperativePromise', Promise, { }, }) return obj }, - /* + /* XXX this for some reason breaks the promise... + // ...the same thing happens if we call .then(..)/.catch(..) __init__: function(){ // if we are fulfilled before being set, we are set :) this.finally(function(){ @@ -127,7 +133,7 @@ object.Constructor('_CooperativePromise', Promise, { value: function(promise){ // get state... if(arguments.length == 0){ - return !!methods } + return !methods } if(methods){ // non-promise... if(promise.catch == null && promise.then == null){ diff --git a/package.json b/package.json index 7d39408..4b365d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ig-types", - "version": "3.0.3", + "version": "3.1.0", "description": "Generic JavaScript types and type extensions...", "main": "main.js", "scripts": { diff --git a/test.js b/test.js index 26501c1..dfdfbb1 100755 --- a/test.js +++ b/test.js @@ -14,6 +14,7 @@ var object = require('ig-object') var types = require('./main') var containers = require('./containers') +var promise = require('./Promise') @@ -104,7 +105,8 @@ var cases = test.Cases({ }, Promise: function(assert){ - var p = assert(Promise.cooperative()) + var p = assert(Promise.cooperative(), '.cooperative()') + //var p = assert(promise._CooperativePromise()) assert(!p.isSet, '.isSet is false') @@ -112,24 +114,35 @@ var cases = test.Cases({ var then p.then(function(v){ - console.log('then') - then = RESOLVE }) + // 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 = v }) assert(!p.isSet, '.isSet is false') var fin p.finally(function(){ - console.log('finally') fin = true }) assert(!p.isSet, '.isSet is false') - // XXX for some reason this does not resolve p... - p.set(123) + p.set(RESOLVE) assert(p.isSet, '.isSet') - assert(then == RESOLVE, '.then(..)') - assert(fin, '.finally(..)') + + // 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) }, // Date.js @@ -226,6 +239,31 @@ var cases = test.Cases({ +//--------------------------------------------------------------------- + +var PromiseTests = test.TestSet() +test.Case('PromiseTests', PromiseTests) + +PromiseTests.setups({ + cooperative: function(assert){ + return { + a: assert(Promise.cooperative(), '.cooperative()') + } }, + experimental: function(assert){ + return { + a: assert(promise._CooperativePromise(), 'experimental') + } }, +}) + +PromiseTests.modifiers({ +}) + +PromiseTests.tests({ + +}) + + + //--------------------------------------------------------------------- // UniqueKeyMap testing...