cleanup and tweaking...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-11-16 02:38:19 +03:00
parent 0bc34d8a60
commit 4ddb927934
5 changed files with 68 additions and 170 deletions

View File

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

View File

@ -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)
- [`<obj>.on(..)`](#objon)
- [`<obj>.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`
#### `<obj>.on(..)`

View File

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

View File

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

View File

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