These are chat archives for canjs/canjs

29th
Mar 2016
Christopher Oliphant
@RALifeCoach
Mar 29 2016 00:05
I am busy for a bit
Christopher Oliphant
@RALifeCoach
Mar 29 2016 00:57
I have it working - somewhat
have a look at the js bin, when you are free
Christopher Oliphant
@RALifeCoach
Mar 29 2016 01:18
In my code version, as opposed to my JS Bin version, I added a setter on player. It is getting called before parseModel. Any ideas why?
@Bajix reading the documentation, it says that parseModel is never called directly, "Instead the deferred returned by findOne, update, and create is piped into parseModel."
Thomas Sieverding
@Bajix
Mar 29 2016 01:21
@RALifeCoach That’s correct. When you can model/models it’ll call parseModel internally
You shouldn’t ever call it directly
Christopher Oliphant
@RALifeCoach
Mar 29 2016 01:28
then please help me out here
how do I get the parseModel to be called without an ajax call being made?
Thomas Sieverding
@Bajix
Mar 29 2016 01:28
You call the model/models function on your can.Model constructor
Christopher Oliphant
@RALifeCoach
Mar 29 2016 01:28
do I override makeCallOne and then model.callOne()?
Thomas Sieverding
@Bajix
Mar 29 2016 01:29
All you need to do is call something like User.models(data)
Christopher Oliphant
@RALifeCoach
Mar 29 2016 01:29
model/models have been deprecated
as of 2.1
Thomas Sieverding
@Bajix
Mar 29 2016 01:31
You’re misunderstanding that statement. models/model is not deprecated
@RALifeCoach The functionality changed, that is all
Christopher Oliphant
@RALifeCoach
Mar 29 2016 01:36
I instantiate the model passing no data. I then say: this.playerRowModel.model(data); and get the error "models is not a function"
I tried model and models
Thomas Sieverding
@Bajix
Mar 29 2016 01:38
It’s a method on the constructor, not on the prototype
Christopher Oliphant
@RALifeCoach
Mar 29 2016 01:39
right
Thomas Sieverding
@Bajix
Mar 29 2016 01:40
Does that solve your issue?
Oh you need to extend can.Model instead of can.Map
That’s maybe your issue
Christopher Oliphant
@RALifeCoach
Mar 29 2016 01:41
I am extending can.Model
Thomas Sieverding
@Bajix
Mar 29 2016 01:41
I see none of this in your codes
Christopher Oliphant
@RALifeCoach
Mar 29 2016 01:42
var PlayerRowMap = can.Model.extend({
Thomas Sieverding
@Bajix
Mar 29 2016 01:42
Ok so then do PlayerRowMap.models
Christopher Oliphant
@RALifeCoach
Mar 29 2016 01:45
I am sorting out some bugs in the code
Christopher Oliphant
@RALifeCoach
Mar 29 2016 02:02
okay - some updates - the mapping is not taking a really long time - 4 seconds for all 156 rows
@Bajix and it seems like I lost some attributes
Christopher Oliphant
@RALifeCoach
Mar 29 2016 02:09
I also seem to have put jsbin into a loop
I am off to bed - I get up very early
thanks for your help - I will update you tomorrow with any progress
Thomas Sieverding
@Bajix
Mar 29 2016 02:10
np
Christopher Oliphant
@RALifeCoach
Mar 29 2016 02:11
One question - would take the returned value from parseModel and use it to instantiate a Map or Model?
Thomas Sieverding
@Bajix
Mar 29 2016 02:11
re: infinite loop, you need to set the value to the result of calling model
So if (foo.bar) { foo.bar = Bar.model(foo.bar) }
Christopher Oliphant
@RALifeCoach
Mar 29 2016 02:12
I have var data = Model.model(request);
I then say, playerRowMap = new Model(data);
Thomas Sieverding
@Bajix
Mar 29 2016 02:12
parseModel: function( data, xhr ) {
  if (typeof data === 'string') {
    return {
      _id: data
    };
  }

  var __v = data.__v,
    _id = data._id;

  if (_id && typeof __v === 'number' && Channel.store.hasOwnProperty(_id)) {
    var channel = Channel.store[_id];

    if (channel.__v > __v) {
      delete data.__v;
      delete data.userCount;
      delete data.guestCount;
    }
  }

  can.batch.start();

  [
    'moderators',
    'bannedUsers',
    'bootedUsers'
  ].forEach(function( key ) {
    if (data.hasOwnProperty(key)) {
      data[key] = User.models(data[key]);
    }
  });

  if (data.owner) {
    can.extend(data.owner, {
      isModerator: true,
      isOwner: true
    });

    data.owner = User.model(data.owner);
  }

  can.batch.stop();

  return data;
},
Use it like that
Christopher Oliphant
@RALifeCoach
Mar 29 2016 02:13
that doesn’t answer my question
Thomas Sieverding
@Bajix
Mar 29 2016 02:13
No that’s not how it works
model returns an instance
Christopher Oliphant
@RALifeCoach
Mar 29 2016 02:14
instance of?
Thomas Sieverding
@Bajix
Mar 29 2016 02:14
And you don’t pass it the promise, you pipe it the AJAX request
Christopher Oliphant
@RALifeCoach
Mar 29 2016 02:14
Model?
Thomas Sieverding
@Bajix
Mar 29 2016 02:14
yes
Christopher Oliphant
@RALifeCoach
Mar 29 2016 02:14
I DON’T HAVE AJAX
I have said that so many times now.
Thomas Sieverding
@Bajix
Mar 29 2016 02:14
Whatever the data source is, doesn’t matter, I was giving you an example
Christopher Oliphant
@RALifeCoach
Mar 29 2016 02:15
I have a player object - that’s it
Thomas Sieverding
@Bajix
Mar 29 2016 02:15
var playerRowMap = PlayerRowMap.model(myDataPJSO)
That’s it
Christopher Oliphant
@RALifeCoach
Mar 29 2016 02:15
okay
Thomas Sieverding
@Bajix
Mar 29 2016 02:15
playerRowMap instanceof PlayerRowMap === true
Christopher Oliphant
@RALifeCoach
Mar 29 2016 02:17
alright - that worked and is better timing then my last attempt
however, the updating is still taking a while
Thomas Sieverding
@Bajix
Mar 29 2016 02:17
One issue at a time
Christopher Oliphant
@RALifeCoach
Mar 29 2016 02:18
alright then suggest how best I update the model for maximum efficiency
I will read your response in the morning
Thomas Sieverding
@Bajix
Mar 29 2016 02:19
1) Pass around map instances instead of cross-binding properties to components
2) Use one-way binding whenever applicable
3) Use leakScope: false whenever applicable
4) Use ./ within your bindings
Thomas Sieverding
@Bajix
Mar 29 2016 02:27
5) Use computes like a mad man. The goal is to lower unnecessary change events. For example, the isAdmin getter I described above is actually really performant, as now I can bind to it elsewhere, and something like changing users or logging in that would trigger isAdmin to be re-computed wouldn’t trigger other computes that are dependent on isAdmin from re-computing if isAdmin doesn’t change
isAdmin: {
  get: function() {
    var profile = this.attr('profile');

    if (profile) {
      return profile.attr('tier') === config.tiers.indexOf('admin');
    }

    return false
  }
}
Changing profile / tier would recompute this. But if the value hasn't changed, computes dependent on this wouldn't recompute
Julian
@pYr0x
Mar 29 2016 09:35
@Bajix you mean, that computes are cached...?
how look like the worse isAdmin method?
Christopher Oliphant
@RALifeCoach
Mar 29 2016 12:20
@pYr0x parseModel isn’t producing any better results than simply using type: ‘*’ for objects not needing observables
Julian
@pYr0x
Mar 29 2016 12:27
ok.. and what about the point 5) bajix said?
also 3) and 4) are good points
to look at
Christopher Oliphant
@RALifeCoach
Mar 29 2016 12:28
computes give a way to handle events outside of the component when attributes within the map associated with the component change
I don’t really have a need for that
When I turned on leakScope - everything stopped working
All my data is in the viewModel, not in the outer scope
I haven’t tried ./ and I must confess I am not sure what that means
I don’t recall seeing that in the docs
Christopher Oliphant
@RALifeCoach
Mar 29 2016 12:40
@pYr0x can you please point to the docs for ./
Jeroen Cornelissen
@jeroencornelissen
Mar 29 2016 12:43
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:09
Thanks
Kevin Phillips
@phillipskevin
Mar 29 2016 13:31
@RALifeCoach one thing I would test is how much of the DOM is being updated when you make a change
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:32
sure
Kevin Phillips
@phillipskevin
Mar 29 2016 13:32
you can turn on paint rectangles in chrome dev tools
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:32
how do you want to do that?
then when you change something, the piece of the DOM that was updated should flash green
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:49
I am not seeing any of it flash green during load or reload
Kevin Phillips
@phillipskevin
Mar 29 2016 13:49
ok, when you say “updating is taking a while” what do you mean exactly?
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:51
var stache1 = new Date().getTime();
                this.playerRowMap.attr({'player': request.player});
var stache2 = new Date().getTime();
pgatour.stacheTime += stache2 - stache1;
at the end of 156 updates the total accumulated time is 1.8 seconds
Kevin Phillips
@phillipskevin
Mar 29 2016 13:51
but that’s not noticeable by the user?
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:52
I notice it
Kevin Phillips
@phillipskevin
Mar 29 2016 13:52
how?
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:52
and I am on a high end MAC Pro
I haven’t tried it on my phone yet
I can see the delay
2 seconds is a noticeable delay
Kevin Phillips
@phillipskevin
Mar 29 2016 13:53
so… you click a button and expect new data to be shown, but it takes time
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:53
that’s right
Kevin Phillips
@phillipskevin
Mar 29 2016 13:53
but during that time, the browser isn’t locked… you can scroll, or click other things
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:53
and it is a conversion of existing code that uses jQuery tmpl - that time to reload was .4 seconds
and if I write code to strip down my player object from hundreds of properties to the 30 or so I need, I get close to the .4 second reload time
Kevin Phillips
@phillipskevin
Mar 29 2016 13:55
ok, yeah, I’ve been reading some of the earlier conversation
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:56
I have used type: ‘*’ and parseModel - both gave the same improvement - down from 6 seconds to reload
Kevin Phillips
@phillipskevin
Mar 29 2016 13:56
so I’m still a little confused
when you notice the delay, what are you expecting to change?
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:56
nothing
Kevin Phillips
@phillipskevin
Mar 29 2016 13:57
so… you click a button and expect new data to be shown, but it takes time
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:57
It is actually a very long and complicated page load - the data is loaded once and then reloaded with more details
Kevin Phillips
@phillipskevin
Mar 29 2016 13:57
ok
so you’re expecting the entire screen to change?
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:57
I have added the timing code to find out why those two steps were taking so long
I can’t do anything to reduce the initial load
That’s why I am now focusing on the reload
Kevin Phillips
@phillipskevin
Mar 29 2016 13:59
sure
Christopher Oliphant
@RALifeCoach
Mar 29 2016 13:59
Justin suggested lazy map and I was seeing timings where I wanted them to be
But lazy map is broken with more complex data
I was really hoping someone would fix lazy map
Kevin Phillips
@phillipskevin
Mar 29 2016 14:01
is there an open issue?
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:01
yes
Kevin Phillips
@phillipskevin
Mar 29 2016 14:02
about LazyMap I mean
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:02
canjs/can-map-lazy#1
Kevin Phillips
@phillipskevin
Mar 29 2016 14:02
thanks
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:03
Do you have any new suggestions? Can you schedule a fix to lazy map?
Kevin Phillips
@phillipskevin
Mar 29 2016 14:05
if it’s not a DOM update that is causing the problem (which you ruled out using paint flashes) I don’t have any new suggestions right now
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:05
and lazy map?
Kevin Phillips
@phillipskevin
Mar 29 2016 14:05
I can take a look at LazyMap
but I can’t promise anything
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:06
it is simple to re-create
Kevin Phillips
@phillipskevin
Mar 29 2016 14:06
ok, if you can track down the exception, PRs are always welcome
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:07
I found the exception, but I just don’t know the code well enough to to create a PR
define('can/map/lazy/lazy', [
    'can/util/util',
    'can/map/lazy/bubble',
    'can/map/map_helpers',
    'can/map/map',
    'can/list/list',
    'can/map/lazy/nested_reference'
], function (can, bubble, mapHelpers) {
    can.LazyMap = can.Map.extend({ _bubble: bubble }, {
        setup: function (obj) {
            this.constructor.Map = this.constructor;
            this.constructor.List = can.LazyList;
            this._data = can.extend(can.extend(true, {}, this._setupDefaults() || {}), obj);
            can.cid(this, '.lazyMap');
            this._setupComputedProperties();
            var teardownMapping = obj && mapHelpers.addToMap(obj, this);
            this._nestedReference = new can.NestedReference(this._data);
            if (teardownMapping) {
                teardownMapping();
            }
            can.each(this._data, can.proxy(function (value, prop) {
                this.___set(prop, value);
            }, this));
            this.bind('change', can.proxy(this._changes, this));
        },
        _changes: function (ev, attr, how, newVal, oldVal) {
        },
        _addChild: function (path, newChild, setNewChild) {
            var self = this;
            this._nestedReference.removeChildren(path, function (oldChild, oldChildPath) {
                bubble.remove(self, oldChild);
                if (newChild) {
                    var newChildPath = oldChildPath.replace(path + '.', '');
                    if (path === newChildPath) {
                        oldChild._nestedReference.each(function (obj, path) {
                            newChild._nestedReference.make(path());
                            if (self._bindings) {
                                bubble.add(this, newChild, path());
                            }
                        });
                    } else {
                        var reference = newChild._nestedReference.make(newChildPath);
                        if (self._bindings) {
                            bubble.add(oldChild, newChild, reference());
                        }
                    }
                }
            });
            if (setNewChild) {
                setNewChild();
            }
the line throwing the exception is oldChild._nestedReference.each(_nestedReference is null
oldChild is not a type Constructor, but an Object
Kevin Phillips
@phillipskevin
Mar 29 2016 14:12
ok
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:16
@phillipskevin do you have an estimate as to when you can have a look?
Kevin Phillips
@phillipskevin
Mar 29 2016 14:22
I am traveling at a client this week so not really.
I’m going to look at the issue today, but don’t have any idea if I’ll know how to fix it.
Julian
@pYr0x
Mar 29 2016 14:24
@RALifeCoach can you reproduce this issue with lazymap on a simple and short example
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:24
I knew someone was going to ask that. Yes I can.
Julian
@pYr0x
Mar 29 2016 14:25
;) we have to make tests for CI
so a test that reproduce this problem is the first step to fix this
btw. can-map-lazy is currently for canjs 3.0
not for 2.x
Kevin Phillips
@phillipskevin
Mar 29 2016 14:27
thanks, I was trying to figure that out
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:27
I know it’s scheduled for 3.0, but gave me the best performance improvement so far
Kevin Phillips
@phillipskevin
Mar 29 2016 14:28
require(‘can/map/lazy'); without installing can-map-lazy
there is a can.LazyMap plugin for 2.x also
right @pYr0x ?
Julian
@pYr0x
Mar 29 2016 14:29
lazymap is currently (in canjs 2.x) integrated.
if i understand right, you have problems with nested properties?
Kevin Phillips
@phillipskevin
Mar 29 2016 14:30
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:31
yes - nested properties are causing the problem
Julian
@pYr0x
Mar 29 2016 14:32
@phillipskevin yep, lazymap extends can.map
@RALifeCoach this stache isnt very short
and the test also
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:32
Sorry - I can pare it down
Julian
@pYr0x
Mar 29 2016 14:32
why?
this code isnt a testable code...
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:40
it is much shorter now
Julian
@pYr0x
Mar 29 2016 14:43
so we need the component?
can you remove that
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:44
Better?
Julian
@pYr0x
Mar 29 2016 14:46
didnt see any changes?
still a component
yes there is still a component
how’s how my code works
Julian
@pYr0x
Mar 29 2016 14:47
can you remove that too
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:49
When I removed the component it stopped crashing
Julian
@pYr0x
Mar 29 2016 14:50
;)
good to know
so the problem is not lazymap
it is the component?
the line of code that is throwing the exception is in lazy map
Julian
@pYr0x
Mar 29 2016 14:51
yes.. but the problem can come from other code
Kevin Phillips
@phillipskevin
Mar 29 2016 14:51
the component probably causes lazyMap to set up the binding
the component binds, and lazymap tries to initialize the data
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:52
it has to do with observables - and the component is the one telling lazy map to create the observable. If I knew the canJS code better, I could probably re-create without the component.
Kevin Phillips
@phillipskevin
Mar 29 2016 14:53
just do theMap.bind(‘whatever.data.that.fails’, function() { … })
to bind to the map manually
Christopher Oliphant
@RALifeCoach
Mar 29 2016 14:56
that didn’t crash either
At this point, the code is as small as I can make it and still have it crash. The bug may be in lazy map, it may be in component, it may be somewhere else altogether.
here is the latest - I will also post the link in the issue
Kevin Phillips
@phillipskevin
Mar 29 2016 17:27
@RALifeCoach so your performace is better now using LazyMap?
Christopher Oliphant
@RALifeCoach
Mar 29 2016 17:28
I am working through the changes now and I will keep you posted
the update is now down to 1 second
I was really hoping to have it lower
in the .6-.8 range
Christopher Oliphant
@RALifeCoach
Mar 29 2016 18:02
            var template = can.stache('<player-row id="player-row-{{pid}}" {pid}="pid" {parent}="parent"></player-row>');
            var fragment = template({
                pid: this.pid,
                parent: this
            });
the player-row component has a viewModel and in the viewModel there is a set on pid. However, the set isn’t getting called. Instead the component starts trying to fill out the fragment from it’s stache view.