Giter VIP home page Giter VIP logo

falcor's People

Contributors

bcardi avatar drager avatar dzannotti avatar falcor-build avatar giovannicalo avatar jayphelps avatar jcouyang avatar jhamlet avatar jhusain avatar jmbattista avatar jontewks avatar ktrott avatar lmeyerov avatar lrowe avatar megawac avatar mik01aj avatar msweeney avatar nickmerwin avatar nicolasartman avatar ning-github avatar patrickjs avatar pdehaan avatar prayagverma avatar rmeshenberg avatar sdesai avatar seanpoulter avatar theprimeagen avatar tivac avatar trxcllnt avatar weiland avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

falcor's Issues

falcor-router wrong path resolution.

Handling a path with the form of:

"foo.WHATEVER"{
  call(pathSet, args) {
    return [
        {
          "path": [
            "bar",
            "baz"
          ],
          "value": 1
        },
        {
          "path": [
            "foo",
            "zap",
            0
          ],
          "value": 2
        }
    ]
  }
}

The resullting jsonGraph will be:

{
  foo: {
    "bar":{
      "baz":1 //WRONG
    },
    "zap":{
      0:2
    }
  }
}

While on falcor-router the same response has the correct structure

{
  "bar":{
    "baz":1 
  foo: {
    "zap":{
      0:2
    }
  }
}

The first path is concatenated with the root (thisPath) of the call path, the remaining paths goes unchanged

Connect Falcor model to react

This is not really an issue at all, so I can migrate elsewhere if you think there's a better place to discuss.

After trying out a bunch of different patterns for integrating Falcor into a React app (in my case backed by a Redux store, though that wasn't a hard requirement), I came up with the following naive approach, based in large part on some of the approaches you take in falcor-react-redux/falcor-react-schema.

// initialize model with change$ stream
const change$ = new BehaviorSubject();

const model = new Model({
  source: new LocalDatasource(graph),
  onChange: () => change$.next()
})
  .batch()
  .boxValues()
  .treatErrorsAsValues();

// create connectFalcor HOC
const connectFalcor = propsToGraphStream => BaseComponent =>
  hoistStatics(compose(
    setDisplayName(wrapDisplayName(BaseComponent, 'Falcor')),
    getContext({ falcor: PropTypes.object }),
    mapPropsStream(props$ => props$
      .merge(change$.withLatestFrom(
        props$,
        (_, props) => props
      ))
      .switchMap(
        ({ falcor, ...props }) => propsToGraphStream(props, falcor),
        ({ falcor, ...props }, falcorResponse) => ({ ...props, falcorResponse })
      )
      .auditTime(0, animationFrame)
    )
  ))(BaseComponent);

// connect an example todo component
const ConnectedTodoList = compose(
  // optionally connect to Redux store, though props needed for falcor request
  // could just as easily be passed as props to the connected HOC
  connectRedux(state => ({
    range: state.todos.range
  })),
  connectFalcor(({ range }, falcor) =>
    Observable.from(falcor.get(
      ['todos', range, ['title', 'status', 'createdAt']],
      ['todos', 'length']
    ).progressively())
  ),
  // optionally deserialize the falcor response
  mapProps(({ range, falcorResponse: jsonEnvelope }) => ({
    todosLength: jsonEnvelope.json.todos.length,
    todos: jsonEnvelope.json.todos.slice(range.from, range.to).map(deserializeTodo)
  }))
)(TodoList);

So far, everything works pretty well for the few use cases I've come across so far. Curious if you have any feedback, and whether or not this tracks at all with what you are trying to do w/ falcor-react-redux/falcor-react-schema.

There are some notable potential performance issues where the wrapped component will be updated unnecessarily:

  • if the props passed to the connected HOC change, but the new props don't actually result in a new falcorPath, the falcor model will be queried anyway. It'll hit the cache, so no significant performance issue, but arguably the request shouldn't be made in the first place if the path is unchanged
  • if the change$ stream emits a change event, but the change does not affect the part of the graph the connected HOC is subscribed to, the falcor model will again be queried and the wrapped component updated (though the render will likely no-op, as the props haven't actually changed). Again, arguably the component shouldn't update at all. This is why you are tracking version on the falcorJSON?

Anyhow, thought I'd share. And thanks for open sourcing the work you've done, which all of the above is based on.

simultaneous requests against model w/ recycleJSON returns duplicate data

const model = new Model({
  source: new DataSource(...),
  recycleJSON: true
});

model.get(['search', 'EORJy', 'match', 'length'])
  .subscribe({
    next(res) { console.log('search result:', res); }
  });

model.get(['thing', '1ZJya', 'defaultLabel'])
  .subscribe({
    next(res) { console.log('item result:', res); }
  });

// > "search result: { json: { search: EORJy: { ... } } }
// > "item result: { json: { search: EORJy: { ... } } }

The model behaves as expected when recycleJSON: true is removed. Also, this does not appear to occur when I change model.get to model.getValue, or make the second get request after the first has resolved.

iterate FalcorJSON instance

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

access absolute/resolved/dereferenced path

Curious to know if you have a public api to access a node's absolute path (aka it's resolved/dereferenced path). I was surprised Netflix didn't expose this easily, except through acrobatics like

model.deref(["users", 0], "name").subscribe(function(userModel){
  console.log(userModel.getPath());
  // > ["usersById", 32]
});

// or

model.boxValue().get(['users', 0]).subscribe((res) => {
  console.log(res.json)
  // > { $type: 'ref', value: ["usersById", 32] }
});

I noticed that you stored path metadata under the JSONGraph's private f_meta.abs_path property. Is there any way to access this property?

Inconsistencies in Error reporting between recycleJSON true and false

const model = new Model({
  source: {
    get: () => Observable.timer(100)
      .concat(Observable.throw({
        status: 500
      }))
  },
  recycleJSON
})


model.get(['items', 0, 'title'])  
  .subscribe({
    error(err) {
      console.log('Error', err)
    }
  });

If recycleJSON is true, logs:

// > { $type: 'error', value: { status: 500 } }

If recycleJSON is false, logs:

// > [{ "path": ["items", 0, "title"], "value": { "status":500 } }]

falcor-react-redux: connected HOC does not receive parent props

In cases like this:

const ComponentWithFalcor = connect(SomeComponent);

render((
  <ComponentWithFalcor someProp="value" />
), document.getElementById('app'));

the inner SomeComponent won't receive the prop someProp. It looks like this is b/c mergeReduxProps (here) only passes falcor from the third ownProps argument.

Unless I'm missing something, mergeProps isn't necessary here. I tried changing to

connectRedux(mapReduxStoreToProps, null, null, reduxOptions),

and it seemed to work. Haven't tested properly, though, b/c I haven't gotten the lerna build working...

Metadata is lost when returning sentinel from datasource

For context, this is in relation to this ticket. Requests that return 400/500 populate the graph w/ error sentinels, and subsequent retries simply hit the cache, rather than actually making the API call again. Being able to set expiry metadata on sentinels returned from the datasource would solve this. But it looks like metadata is not actually applied to nodes in the cache (though if I'm reading this correctly, it looks like it should...).

E.g.

  observer.onError({
    $type: 'error',
    value: {
      message: errorMessage,
      status
    },
    $expires: 1
  });

I still need to confirm whether or not this is happening in the original Netflix implementation.

FalcorJSON $__status is 'resolved' when model progressively returns partial response from cache

Is the FalcorJSON.$__status property supposed to reliably determine whether or not a model query is done emitting?

I'm running into the following issue:

  1. model cache is populated with some results, e.g. [search, 1, { to: 9 }, title]

  2. query model that emits progressively for paths, some of which can resolve in the local cache

model.get(['search', 1, { to: 19 }, 'title']).progressively()
  .subscribe({
    next(falcorJSON => {
      console.log('response:', falcorJSON.json.search[1]);
      console.log('status:', falcorJSON.json.$__status);
    })
  });
  1. model emits twice, first with partial response from cache, second with total response. But each time w/ resolved status
// > response: { 0: { title: '...' }, ..., 9: { title: '...' } }
// > status: resolved
// sometime later...
// > response: { 0: { title: '...' }, ..., 19: { title: '...' } }
// > status: resolved

Is this a correct usage of $__status?

Error in webpack "promise" module can not be found

@trxcllnt getting the following error when building with webpack:

ERROR in ./~/@graphistry/falcor/dist/falcor.min.js
Module not found: Error: Cannot resolve module 'promise' in node_modules/@graphistry/falcor/dist
 @ ./~/@graphistry/falcor/dist/falcor.min.js 4:288-306

I can work around it by installing the promise module in my devDependencies, but you probably have a dangling require somewhere that is making webpack try to load it just in case.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.