added StopIteration support to chunk iteration...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-11-05 16:40:41 +03:00
parent b0aaf54764
commit 6e68d08b06
4 changed files with 106 additions and 23 deletions

View File

@ -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))

View File

@ -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){

View File

@ -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": {

54
test.js
View File

@ -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...