graphistry / falcor

Graphistry forks of the FalcorJS family of projects in a lerna-powered mono-repo.
23 stars 3 forks source link

iterate FalcorJSON instance #10

Closed jameslaneconkling closed 7 years ago

jameslaneconkling commented 7 years ago

(continues discussion at end of issue thread #8)

So, the use case is iterating a FalcorJSON response instance while avoiding metadata. As @trxcllnt points out, b/c the FalcorJSON class copies methods from the Array.prototype, you can use map/reduce/filter/etc. assuming the FalcorJSON instance has a numeric length property.

However, this doesn't work if using boxValues to make requests, as length resolves to an Object (e.g. { $size: 51, $type: "atom", value: 1221 }).

I was considering overwriting the FalcorJSON methods to use the length boxedValue at length.value, using a polyfill as a guide , but realized that for cases where I was working with graph fragments with large indices, (e.g. ['todos', { from: 1000, to: 1010 }, ...]), there would be unnecessary overhead.

So, instead I wrote a pretty naive utility function

const mapFalcorJSON2Array = (project, from, to, falcorJSON) => {
  const result = [];

  while (from <= to) {
    result.push(project(falcorJSON[from], from));
    from += 1;
  }

  return result;
};

// e.g.
mapFalcorJSON2Array((todo, idx) => ({ ...todo, idx }), 1000, 1010, todosFalcorJSON)

Not sure if there are better/more general solutions. @trxcllnt thoughts.

trxcllnt commented 7 years ago

@jameslaneconkling That looks good to me. I initially thought about adding a method like this to the prototype, but realized slice also does the job: falcorList.slice(1000, 1010).map(() => ).

As for boxed values, the only solution I saw was calling each Array method with the boxed length value, essentially changing this function to read:

function bindArrayMethod(name, fn) {
    return new Function('fn', 'aSlice',
        'return function ' + name + ' () {' +
            'var arr = this, length = this.length;' +
            'if ((typeof length === "object") && typeof (length = length.value) === "number") {' +
                'arr = aSlice.call(this, 0, length);' +
            '}' +
            'return fn.apply(arr, arguments);' +
        '};'
    )(fn, Array.prototype.slice)
}
trxcllnt commented 7 years ago

@jameslaneconkling Just published 2.7.0 with this fix

jameslaneconkling commented 7 years ago

Oh, this is very cool--thanks for the update. Just took it for a test and it works as expected when length is an atom.

I think that closes this out. Feel free to reopen if you have any additional thoughts/updates on the matter.