From 4ddb92793408cefc70c017ad6afc3290ea9fee41 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Mon, 16 Nov 2020 02:38:19 +0300 Subject: [PATCH] cleanup and tweaking... Signed-off-by: Alex A. Naanou --- Promise.js | 198 +++++++++++++-------------------------------------- README.md | 6 ++ package.json | 2 +- runner.js | 26 +++---- test.js | 6 +- 5 files changed, 68 insertions(+), 170 deletions(-) diff --git a/Promise.js b/Promise.js index 3e88376..cfce406 100644 --- a/Promise.js +++ b/Promise.js @@ -12,153 +12,40 @@ var object = require('ig-object') /*********************************************************************/ -var CooperativePromise = -module.CooperativePromise = -Promise.cooperative = -object.Constructor('CooperativePromise', Promise, { - get isSet(){ - return !this.__resolve && !this.__reject }, - - set: function(promise){ - if(!this.isSet){ - // non-promise... - if(promise.catch == null && promise.then == null){ - this.__resolve(promise) - // promise... - } else { - // connect the base and the set promises... - promise.catch(this.__reject.bind(this)) - promise.then(this.__resolve.bind(this)) } - // cleanup... - delete this.__resolve - delete this.__reject - - return this } - - // err: already set... - throw new Error('CooperativePromise.set(..): can not set twice') }, - - __new__: function(_, func){ - var methods = {} - var obj = Reflect.construct(CooperativePromise.__proto__, [ - function(resolve, reject){ - 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 - delete obj.__reject - }) }, 0) - //*/ - // XXX revise... - // XXX can we avoid creating these??? - // ...one way to do this is to create a local .set(..) - // that whould reference them through closure... - Object.defineProperties(obj, { - __resolve: { - value: methods.resolve, - enumerable: false, - configurable: true, - }, - __reject: { - value: methods.reject, - enumerable: false, - configurable: true, - }, - }) - 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(){ - delete this.__resolve - delete this.__reject - }.bind(this)) }, - //*/ -}) - - - -// XXX EXPERIMENTAL -- this hides internal state (.__resolve(..) / .__reject(..)) -// ...not sure if we actually need to do this... -var _CooperativePromise = -module._CooperativePromise = -//Promise.cooperative = -object.Constructor('_CooperativePromise', Promise, { - get isSet(){ - return this.set() }, - - //set: function(){}, - - __new__: function(_, func){ - // internal state... - // NOTE: when promise is set this will be set to false... - var methods = {} - - // instance... - var obj = Reflect.construct(_CooperativePromise.__proto__, [ - function(resolve, reject){ - methods.resolve = resolve - methods.reject = reject - // NOTE: this is here mostly for promise compatibilty... - if(func){ - // XXX this can resolve/reject a 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... - setTimeout(function(){ - obj.finally(function(){ - methods = false }) }, 0) - - // create instance .set(..) - Object.defineProperty(obj, 'set', { - value: function(promise){ - // get state... - if(arguments.length == 0){ - return !methods } - if(methods){ - // non-promise... - if(promise.catch == null && promise.then == null){ - methods.resolve(promise) - // promise... - } else { - // connect the base and the set promises... - promise.catch(methods.reject.bind(this)) - promise.then(methods.resolve.bind(this)) } - methods = false - return this } - // err: already set... - throw new Error('CooperativePromise.set(..): can not set twice') }, - enumerable: false, - configurable: true, - }) - - return obj }, -}) +// XXX does this need to be a distinct object??? +Promise.cooperative = function(){ + var handlers + return object.mixinFlat( + new Promise(function(resolve, reject){ + handlers = { resolve, reject, } }), + { + get isSet(){ + return handlers === false }, + set: function(value){ + // can't set twice... + if(this.isSet){ + throw new Error('Promise.cooperative().set(..): can not set twice') } + // bind to promise... + if(value && value.then && value.catch){ + value.then(handlers.resolve) + value.catch(handlers.reject) + // resolve with value... + } else { + handlers.resolve(value) } + // cleanup and prevent setting twice... + handlers = false + return this }, + }) } //--------------------------------------------------------------------- // promise iterators... +// XXX we need to: +// - wrap each elem in a promise +// - on each map/filter/... chain the handler to each elem and return +// a new iterable with the combination // XXX like Promise.all(..) but creates an iterable promise... var IterablePromise = module.IterablePromise = @@ -168,27 +55,42 @@ object.Constructor('IterablePromise', Promise, { __list: null, map: function(func){ - return IterablePromise() }, - filter: function(func){}, + return IterablePromise(this.__list, function(e, i){ + return [func(e, i)] }) }, + filter: function(func){ + return IterablePromise(this.__list, function(e, i){ + return func(e, i) ? + [e] + : [] }) }, reduce: function(func, res){}, flat: function(){}, all: function(){}, - __new__: function(_, list, handler){ + // XXX how does this support reduce??? + // handler(e, i) + // -> [value] + // -> [] + // + __new__: function(_, list, handler=false){ // instance... var obj = Reflect.construct(IterablePromise.__proto__, [ function(resolve, reject){ // NOTE: this is here for Promise compatibilty... - // XXX this can resolve/reject a promise -- need to - // keep things consistent... if(typeof(list) == 'function'){ return func.call(this, ...arguments) } + var all = Promise.all(list) + // XXX var res = [] - for(var e of list){ - } + list.forEach(function(e, i){ + if(handler && e && e.then && e.catch){ + e.then(function(v){ + return (res[i] = handler(v, i)) }) + + } else { + res[i] = e } }) }], IterablePromise) diff --git a/README.md b/README.md index a1df54f..1666ee7 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ A library of JavaScript type extensions, types and type utilities. - [Event](#event) - [`event.Eventfull(..)`](#eventeventfull) - [`event.Event(..)`](#eventevent) + - [`event.TRIGGER`](#eventtrigger) - [`event.EventHandlerMixin`](#eventeventhandlermixin) - [`.on(..)`](#objon) - [`.one(..)`](#objone) @@ -789,6 +790,11 @@ otherwise [`.unorderedRename(..)`](#unique-key-mapunorderedrename) is called. ### `event.Event(..)` +### `event.TRIGGER` + +Special value when passed to an event method as first argument will force it +to trigger event if the first argument was a function. + ### `event.EventHandlerMixin` #### `.on(..)` diff --git a/package.json b/package.json index 856830a..35414b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ig-types", - "version": "3.7.2", + "version": "3.7.3", "description": "Generic JavaScript types and type extensions...", "main": "main.js", "scripts": { diff --git a/runner.js b/runner.js index 817e6dc..036310b 100644 --- a/runner.js +++ b/runner.js @@ -20,26 +20,14 @@ var object = require('ig-object') +require('./Array') + var events = require('./event') /*********************************************************************/ -// helpers... -/* XXX LEGACY... -var makeEvent = function(func, mode){ - return Object.assign( - func, - {__event__: mode || true}) } -var makeActionEvent = function(func){ - return makeEvent(func, 'action') } -//*/ - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// XXX use ./event... var Queue = module.Queue = object.Constructor('Queue', Array, { // create a running queue... @@ -101,9 +89,15 @@ module.Queue = object.Constructor('Queue', Array, { // - ranges -- simelar to .slice(..) // - by value // XXX - prioritize: function(){}, + prioritize: function(...tasks){ + return this.sortAs(tasks) }, // XXX same as prioritize but adds stuff to the tail... - delay: function(){}, + delay: function(...tasks){ + this.splice(0, this.length, + ...this.slice() + .reverse() + .sortAs(tasks.reverse())) + return this }, // main runner... // diff --git a/test.js b/test.js index 2ef534b..e42c8c3 100755 --- a/test.js +++ b/test.js @@ -111,7 +111,7 @@ var cases = test.Cases({ Promise: function(assert){ var p = assert(Promise.cooperative(), '.cooperative()') //var p = assert(promise._CooperativePromise()) - + assert(!p.isSet, '.isSet is false') var RESOLVE = 123 @@ -253,10 +253,6 @@ PromiseTests.setups({ return { a: assert(Promise.cooperative(), '.cooperative()') } }, - experimental: function(assert){ - return { - a: assert(promise._CooperativePromise(), 'experimental') - } }, }) PromiseTests.modifiers({