mirror of
https://github.com/flynx/types.js.git
synced 2025-10-28 10:00:08 +00:00
added onstop(..) callback to all stoppable funcs...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
47c10ea0b1
commit
9815415827
34
Array.js
34
Array.js
@ -524,19 +524,27 @@ object.Mixin('ArrayProtoMixin', 'soft', {
|
||||
// XXX this should handle throwing STOP!!!
|
||||
// ...might also ne a good idea to isolate the STOP mechanics
|
||||
// into a spearate module/package...
|
||||
iter: stoppable(function*(handler=undefined){
|
||||
if(handler){
|
||||
var i = 0
|
||||
for(var e of this){
|
||||
var res = handler.call(this, e, i++)
|
||||
// treat non-iterables as single elements...
|
||||
if(typeof(res) == 'object'
|
||||
&& Symbol.iterator in res){
|
||||
yield* res
|
||||
} else {
|
||||
yield res } }
|
||||
} else {
|
||||
yield* this }}),
|
||||
iter: stoppable(
|
||||
function*(handler=undefined, onstop){
|
||||
if(handler){
|
||||
var i = 0
|
||||
for(var e of this){
|
||||
var res = handler.call(this, e, i++)
|
||||
// treat non-iterables as single elements...
|
||||
if(typeof(res) == 'object'
|
||||
&& Symbol.iterator in res){
|
||||
yield* res
|
||||
} else {
|
||||
yield res } }
|
||||
} else {
|
||||
yield* this }},
|
||||
// handle stops is onstop(..) is defined...
|
||||
function(res, _, onstop){
|
||||
typeof(onstop) == 'function'
|
||||
&& onstop.call(this,
|
||||
...(res === STOP ?
|
||||
[]
|
||||
: [res])) }),
|
||||
|
||||
|
||||
// Stoppable iteration...
|
||||
|
||||
18
Promise.js
18
Promise.js
@ -255,16 +255,6 @@ object.Constructor('IterablePromise', Promise, {
|
||||
return elem })
|
||||
.flat() },
|
||||
/*/
|
||||
// XXX BUG:
|
||||
// await Promise.iter([Promise.all([1,2,3])], e => e)
|
||||
// await Promise.iter([Promise.iter([1,2,3])], e => e)
|
||||
// -> [1]
|
||||
// the issue is in .__handle(..)'s
|
||||
// elem = elem instanceof Promise ?
|
||||
// elem.then(function([e]){
|
||||
// // XXX
|
||||
// return e })
|
||||
// : ...
|
||||
__pack: function(list, handler=undefined, onerror=undefined){
|
||||
var that = this
|
||||
// handle iterator...
|
||||
@ -315,6 +305,7 @@ object.Constructor('IterablePromise', Promise, {
|
||||
this.__handle(list, handler, onerror)
|
||||
: list },
|
||||
// transform/handle packed array (sync, but can return promises in the list)...
|
||||
// XXX need a strict spec...
|
||||
__handle: function(list, handler=undefined, onerror=undefined){
|
||||
var that = this
|
||||
if(typeof(list) == 'function'){
|
||||
@ -335,17 +326,20 @@ object.Constructor('IterablePromise', Promise, {
|
||||
: 'map'
|
||||
return list
|
||||
[map](function(elem){
|
||||
// XXX need a strict spec...
|
||||
return elem instanceof IterablePromise ?
|
||||
// XXX should this be expanded??? (like Array below)
|
||||
(elem.isSync() ?
|
||||
handler(elem.sync())
|
||||
// XXX need to handle this but keep it IterablePromise...
|
||||
: elem.iterthen(handler))
|
||||
: (elem instanceof SyncPromise
|
||||
&& !(elem.sync() instanceof Promise)) ?
|
||||
// XXX should this be expanded??? (like Array below)
|
||||
handler(elem.sync())
|
||||
// promise / promise-like...
|
||||
: elem && elem.then ?
|
||||
// XXX handle STOP...
|
||||
// XXX handle STOP -- no need to call handlers after a STOP...
|
||||
// ...is there a way to detect STOP from inside .smap(..) ???
|
||||
elem.then(function(elem){
|
||||
return handler(
|
||||
elem.length == 1 ?
|
||||
|
||||
195
generator.js
195
generator.js
@ -91,23 +91,36 @@ function*(lst=[]){
|
||||
} else {
|
||||
yield lst } }
|
||||
|
||||
// handle stops is onstop(..) is defined...
|
||||
var __onstop =
|
||||
function(res, _, ...args){
|
||||
var onstop = args.at(-1)
|
||||
typeof(onstop) == 'function'
|
||||
&& onstop.call(this,
|
||||
...(res === STOP ?
|
||||
[]
|
||||
: [res])) }
|
||||
|
||||
|
||||
// XXX updatae Array.js' version for compatibility...
|
||||
// XXX DOCS!!!
|
||||
var iter =
|
||||
module.iter =
|
||||
Generator.iter =
|
||||
stoppable(function(lst=[]){
|
||||
// handler -> generator-constructor...
|
||||
if(typeof(lst) == 'function'){
|
||||
// we need to be callable...
|
||||
var that = this instanceof Function ?
|
||||
this
|
||||
// generic root generator...
|
||||
: module.__iter
|
||||
return function*(){
|
||||
yield* that(...arguments).iter(lst) } }
|
||||
// no handler -> generator instance...
|
||||
return module.__iter(lst) })
|
||||
stoppable(
|
||||
function(lst=[]){
|
||||
// handler -> generator-constructor...
|
||||
if(typeof(lst) == 'function'){
|
||||
// we need to be callable...
|
||||
var that = this instanceof Function ?
|
||||
this
|
||||
// generic root generator...
|
||||
: module.__iter
|
||||
return function*(){
|
||||
yield* that(...arguments).iter(lst) } }
|
||||
// no handler -> generator instance...
|
||||
return module.__iter(lst) },
|
||||
__onstop)
|
||||
|
||||
// NOTE: we need .iter(..) to both return generators if passed an iterable
|
||||
// and genereator constructos if passed a function...
|
||||
@ -308,31 +321,33 @@ var GeneratorProtoMixin =
|
||||
module.GeneratorProtoMixin =
|
||||
object.Mixin('GeneratorProtoMixin', 'soft', {
|
||||
// XXX use module.iter(..) ???
|
||||
iter: stoppable(function*(handler, onerror){
|
||||
try{
|
||||
if(handler){
|
||||
var i = 0
|
||||
for(var elem of this){
|
||||
var res = handler.call(this, elem, i)
|
||||
// expand iterables...
|
||||
if(typeof(res) == 'object'
|
||||
&& Symbol.iterator in res){
|
||||
yield* res
|
||||
// as-is...
|
||||
} else {
|
||||
yield res }}
|
||||
// no handler...
|
||||
} else {
|
||||
yield* this }
|
||||
}catch(err){
|
||||
if(onerror){
|
||||
if(!(err === STOP
|
||||
|| err instanceof STOP)){
|
||||
var res = onerror(err)
|
||||
if(res){
|
||||
yield res
|
||||
return } } }
|
||||
throw err }}),
|
||||
iter: stoppable(
|
||||
function*(handler, onerror){
|
||||
try{
|
||||
if(handler){
|
||||
var i = 0
|
||||
for(var elem of this){
|
||||
var res = handler.call(this, elem, i)
|
||||
// expand iterables...
|
||||
if(typeof(res) == 'object'
|
||||
&& Symbol.iterator in res){
|
||||
yield* res
|
||||
// as-is...
|
||||
} else {
|
||||
yield res }}
|
||||
// no handler...
|
||||
} else {
|
||||
yield* this }
|
||||
}catch(err){
|
||||
if(onerror){
|
||||
if(!(err === STOP
|
||||
|| err instanceof STOP)){
|
||||
var res = onerror(err)
|
||||
if(res){
|
||||
yield res
|
||||
return } } }
|
||||
throw err }},
|
||||
__onstop),
|
||||
//*/
|
||||
|
||||
at: function(i){
|
||||
@ -396,8 +411,10 @@ object.Mixin('GeneratorProtoMixin', 'soft', {
|
||||
yield* func(e, i++, this) }
|
||||
} else {
|
||||
for(var e of this){
|
||||
yield func(e, i++, this) } } }),
|
||||
filter: stoppable(function*(func){
|
||||
yield func(e, i++, this) } } },
|
||||
__onstop),
|
||||
filter: stoppable(
|
||||
function*(func){
|
||||
var i = 0
|
||||
try{
|
||||
for(var e of this){
|
||||
@ -409,28 +426,36 @@ object.Mixin('GeneratorProtoMixin', 'soft', {
|
||||
if(!err.value){
|
||||
throw STOP }
|
||||
err.value = e }
|
||||
throw err } }),
|
||||
throw err } },
|
||||
__onstop),
|
||||
|
||||
reduce: stoppable(function(func, res){
|
||||
var i = 0
|
||||
for(var e of this){
|
||||
res = func(res, e, i++, this) }
|
||||
return res }),
|
||||
reduce: stoppable(
|
||||
function(func, res){
|
||||
var i = 0
|
||||
for(var e of this){
|
||||
res = func(res, e, i++, this) }
|
||||
return res },
|
||||
// NOTE: we need to wrap __onstop(..) here to prevent res if it
|
||||
// was passed a function from ever being treated as onstop(..)...
|
||||
function(res, f, _, onstop){
|
||||
return __onstop.call(this, res, onstop) }),
|
||||
greduce: function*(func, res){
|
||||
yield this.reduce(...arguments) },
|
||||
|
||||
between: stoppable(function*(func){
|
||||
var i = 0
|
||||
var j = 0
|
||||
var prev
|
||||
for(var e of this){
|
||||
if(i > 0){
|
||||
yield typeof(func) == 'function' ?
|
||||
func.call(this, [prev, e], i-1, i + j++, this)
|
||||
: func }
|
||||
prev = e
|
||||
yield e
|
||||
i++ } }),
|
||||
between: stoppable(
|
||||
function*(func){
|
||||
var i = 0
|
||||
var j = 0
|
||||
var prev
|
||||
for(var e of this){
|
||||
if(i > 0){
|
||||
yield typeof(func) == 'function' ?
|
||||
func.call(this, [prev, e], i-1, i + j++, this)
|
||||
: func }
|
||||
prev = e
|
||||
yield e
|
||||
i++ } },
|
||||
__onstop),
|
||||
|
||||
// NOTE: this is a special case in that it will unwind the generator...
|
||||
// NOTE: this is different from <array>.forEach(..) in that this will
|
||||
@ -566,29 +591,31 @@ object.Mixin('AsyncGeneratorProtoMixin', 'soft', {
|
||||
return this.unwind.finally(...arguments) },
|
||||
|
||||
// XXX might be a good idea to use this approach above...
|
||||
iter: stoppable(async function*(handler=undefined, onerror=undefined){
|
||||
try{
|
||||
var i = 0
|
||||
if(handler){
|
||||
for await(var e of this){
|
||||
var res = handler.call(this, e, i++)
|
||||
if(typeof(res) == 'object'
|
||||
&& Symbol.iterator in res){
|
||||
yield* res
|
||||
} else {
|
||||
yield res } }
|
||||
} else {
|
||||
yield* this }
|
||||
}catch(err){
|
||||
if(onerror){
|
||||
if(!(err === STOP || err instanceof STOP)){
|
||||
var res = onerror(err)
|
||||
if(res !== undefined){
|
||||
yield handler ?
|
||||
handler(res)
|
||||
: res }
|
||||
return } }
|
||||
throw err } }),
|
||||
iter: stoppable(
|
||||
async function*(handler=undefined, onerror=undefined){
|
||||
try{
|
||||
var i = 0
|
||||
if(handler){
|
||||
for await(var e of this){
|
||||
var res = handler.call(this, e, i++)
|
||||
if(typeof(res) == 'object'
|
||||
&& Symbol.iterator in res){
|
||||
yield* res
|
||||
} else {
|
||||
yield res } }
|
||||
} else {
|
||||
yield* this }
|
||||
}catch(err){
|
||||
if(onerror){
|
||||
if(!(err === STOP || err instanceof STOP)){
|
||||
var res = onerror(err)
|
||||
if(res !== undefined){
|
||||
yield handler ?
|
||||
handler(res)
|
||||
: res }
|
||||
return } }
|
||||
throw err } },
|
||||
__onstop),
|
||||
|
||||
map: async function*(func){
|
||||
yield* this.iter(function(elem, i){
|
||||
@ -686,9 +713,11 @@ function*(value=true, stop){
|
||||
|
||||
var produce =
|
||||
module.produce =
|
||||
stoppable(function*(func){
|
||||
while(true){
|
||||
yield func() } })
|
||||
stoppable(
|
||||
function*(func){
|
||||
while(true){
|
||||
yield func() } },
|
||||
__onstop)
|
||||
|
||||
|
||||
|
||||
|
||||
16
package-lock.json
generated
16
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ig-types",
|
||||
"version": "6.24.10",
|
||||
"version": "6.24.11",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ig-types",
|
||||
"version": "6.24.10",
|
||||
"version": "6.24.11",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"ig-object": "^6.0.0",
|
||||
@ -354,9 +354,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ig-stoppable": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ig-stoppable/-/ig-stoppable-2.0.1.tgz",
|
||||
"integrity": "sha512-vos7eFNHryIg6yNzrWTV1QP1Sja5JkMU3nL2Y/YvSgU74l7w1Rx6yfVKoEHwNOex4MCkLsq6wMa91Ac6IWOtIA=="
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/ig-stoppable/-/ig-stoppable-2.0.4.tgz",
|
||||
"integrity": "sha512-KxS8AGsjelRAmbbQuASj+XRuk99P4OOprd+lIUMU2nuRKPQItNQK/apls8IlR3kNp5ZdQqBdV+zVJmYGrxofnA=="
|
||||
},
|
||||
"node_modules/ig-test": {
|
||||
"version": "1.5.4",
|
||||
@ -1073,9 +1073,9 @@
|
||||
}
|
||||
},
|
||||
"ig-stoppable": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ig-stoppable/-/ig-stoppable-2.0.1.tgz",
|
||||
"integrity": "sha512-vos7eFNHryIg6yNzrWTV1QP1Sja5JkMU3nL2Y/YvSgU74l7w1Rx6yfVKoEHwNOex4MCkLsq6wMa91Ac6IWOtIA=="
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/ig-stoppable/-/ig-stoppable-2.0.4.tgz",
|
||||
"integrity": "sha512-KxS8AGsjelRAmbbQuASj+XRuk99P4OOprd+lIUMU2nuRKPQItNQK/apls8IlR3kNp5ZdQqBdV+zVJmYGrxofnA=="
|
||||
},
|
||||
"ig-test": {
|
||||
"version": "1.5.4",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user