These are chat archives for canjs/canjs

28th
Mar 2016
Christopher Oliphant
@RALifeCoach
Mar 28 2016 11:55
@cherifGsoul @justinbmeyer Any progress on the exception being thrown?
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 28 2016 12:36
@RALifeCoach can you make the jsbin works?
@RALifeCoach Justin gave good suggestion as I see
did try that?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 13:04
The jsbin throws the exception I am getting in my code.
Justin suggested adding can-define. A piece of code with no documentation or ability to add to the custom download.
@cherifGsoul LazyMap is broken. See the issue for my comments on when it breaks.
Dovid Bleier
@dbleier
Mar 28 2016 17:07
I have an app, running on a device that downloads images and video to the local file system and then displays them in an HTML/js slideshow sourcing with the file:// protocol in the stache template. If an image has yet to be downloaded, a broken image icon is shown, as expected, until download completes. The issue is that even after downloading, it continues to show the broken image icon and not the newly downloaded image until I refresh the page. I could force an automatic page reload with window.location.reload, but I would prefer not to have to do that. Anyone have an idea how to notify the browser to fetch the image?
Dovid Bleier
@dbleier
Mar 28 2016 20:10
pls ignore previous message. I just got notification from the hardware manufacturer that what I want to do is not possible
another question, is the Promise object/function globally available in donejs or do I need to import (using browser that does not support natively)?
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 28 2016 20:22
@dbleier it's available in jquery and canjs
Dovid Bleier
@dbleier
Mar 28 2016 20:24
so I need import Promise from 'can/promise'; ?
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 28 2016 20:25
no it's available in canjs object I guess
let me make sure
it uses jquery Deferred
Christopher Oliphant
@RALifeCoach
Mar 28 2016 20:28
@cherifGsoul any update on the LazyMap bug and the can-define documentation?
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 28 2016 20:30
@RALifeCoach sorry I was busy, I have never use LazyMap, for can-define you talk about can.map.define plugin?
Dovid Bleier
@dbleier
Mar 28 2016 20:32
@cherifGsoul I thought in 2.3 they moved from deffereds to promises
Promise is part of es6
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 28 2016 20:32
Maybe I missed that
Christopher Oliphant
@RALifeCoach
Mar 28 2016 20:33
I am using can.map.define, although it doesn't seem to work as advertised. There is a separate file can-define which, from a brief glance at the code, gives an option to read data without creating an observable. Is that correct?
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 28 2016 20:33
can-define file? where? the repo in github?
Thomas Sieverding
@Bajix
Mar 28 2016 20:34
@cherifGsoul It’s part of dist
That’s for side-loading plugins w/out using DI
Christopher Oliphant
@RALifeCoach
Mar 28 2016 20:35
Yes there is a repo on github.
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 28 2016 20:35
ok the dist has can.define
Thomas Sieverding
@Bajix
Mar 28 2016 20:36
@RALifeCoach Ignore that repo. It’s not relevant to what you’re doing - CanJS 3.0 is going to be more split up, however that’s not the case with 2.x
Christopher Oliphant
@RALifeCoach
Mar 28 2016 20:37
How do I tell Map or LazyMap that a property does not need an observable.
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 28 2016 20:37
@RALifeCoach the file in the repo not ready for production yet work in progress
please use can.map.define plugin
Thomas Sieverding
@Bajix
Mar 28 2016 20:37
@RALifeCoach Why would you want a property not to be observable?
You can read properties without using .attr if you don’t want them to be observed
You should do that instead
Christopher Oliphant
@RALifeCoach
Mar 28 2016 20:38
@Bajix because the value won't change.
Thomas Sieverding
@Bajix
Mar 28 2016 20:39
All you need to do is read the value directly
Christopher Oliphant
@RALifeCoach
Mar 28 2016 20:39
But a property used within stache is automatically observable.
Thomas Sieverding
@Bajix
Mar 28 2016 20:39
You can also technically use a not observe callback to avoid adding to the stack of observed values
Christopher Oliphant
@RALifeCoach
Mar 28 2016 20:41
Is there any documentation on a "not observe callback"?
And is anyone going to fix LazyMap?
Thomas Sieverding
@Bajix
Mar 28 2016 20:42
How is it broken?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 20:43
Please read the issue I created for lazy map.
Thomas Sieverding
@Bajix
Mar 28 2016 20:43
link
Also can/map/define utilizes computes
It’s just more fine grain
Christopher Oliphant
@RALifeCoach
Mar 28 2016 20:46
I am on my phone, not in front of my computer. I don't have the link. But if you go to github/canjs, and find the link to can/map/lazy
Thomas Sieverding
@Bajix
Mar 28 2016 20:46
I’ll review it tonight
Christopher Oliphant
@RALifeCoach
Mar 28 2016 20:50
Can/map/define uses computes. How do you get it to not use the compute?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 21:46
@Bajix I am back in front of my computer. the link is: canjs/can-map-lazy#1
Thomas Sieverding
@Bajix
Mar 28 2016 21:46
Your issue doesn’t have context
Christopher Oliphant
@RALifeCoach
Mar 28 2016 21:46
there is a JSBin that demonstrates the bug at: http://jsbin.com/wanima/1/edit?html,js,console,output
Thomas Sieverding
@Bajix
Mar 28 2016 21:47
Then update your issue with that
Christopher Oliphant
@RALifeCoach
Mar 28 2016 21:47
the context comes from the original issue: canjs/canjs#2342
Thomas Sieverding
@Bajix
Mar 28 2016 21:47
Also, that repo is for 3.x, and doesn’t apply here
Then add that in your ticket
Nobody can jump into the conversation with what you’ve submitted there
I can look at this, but not now
Christopher Oliphant
@RALifeCoach
Mar 28 2016 21:49
I wanted SOMEONE, anyone to respond. That’s why I opened the second issue
Thomas Sieverding
@Bajix
Mar 28 2016 21:49
Sure, but anyone who looks at that will have no clue what’s going on
Christopher Oliphant
@RALifeCoach
Mar 28 2016 21:50
I don’t have a clue what’s going on. I have asked for help, I get a few suggestions, when I ask for more information I get silence
I was asked to open the original issue, I did, Justin took a brief look, made a couple of suggestions, and then silence
You told me about can.define and computes, when I ask for more information - silence
Thomas Sieverding
@Bajix
Mar 28 2016 21:51
Ok there are multiple issues here
Christopher Oliphant
@RALifeCoach
Mar 28 2016 21:51
Some days you guys are great - other days, very frustrating
Yes. I all started with terrible performance. 4 seconds to load 156 rows and 6 seconds to update the rows.
So I spent a great deal of time creating a JSBin to replicate my problem, because someone asked me to, then no one looked at it.
Julian
@pYr0x
Mar 28 2016 21:53
please share the link again
Justin suggested I use LazyMap. I did and discovered a bug in the LazyMap code.
I have reported the bug, but again - silence
Julian
@pYr0x
Mar 28 2016 21:54
i think lazymap is not future proof
Christopher Oliphant
@RALifeCoach
Mar 28 2016 21:54
sorry - I have found the experience over the weekend frustrating
Julian
@pYr0x
Mar 28 2016 21:54
maybe the problem is a design problem
Thomas Sieverding
@Bajix
Mar 28 2016 21:55
There are guidelines around how to submit issues. We’re very consistent about addressing issues, but you need to be considerate as well. Nobody is being paid to help you here, let alone to drop everything and do so.
Christopher Oliphant
@RALifeCoach
Mar 28 2016 21:55
I CANNOT CHANGE THE DESIGN. I have said this over and over again.
Julian
@pYr0x
Mar 28 2016 21:55
the jsbin is big, and not really good to understand
Christopher Oliphant
@RALifeCoach
Mar 28 2016 21:55
and over and over again
Julian
@pYr0x
Mar 28 2016 21:55
if you dont follow the design pattern, then the performance problems cant be solved
Christopher Oliphant
@RALifeCoach
Mar 28 2016 21:56
I have a 200 line stache file
Julian
@pYr0x
Mar 28 2016 21:56
yep
Christopher Oliphant
@RALifeCoach
Mar 28 2016 21:56
I have made every recommendation you guys have asked me to make
Thomas Sieverding
@Bajix
Mar 28 2016 21:56
@RALifeCoach I’ll look into it when I’m free today, all I ask is that you read up on the community guidelines for submitting issues
Christopher Oliphant
@RALifeCoach
Mar 28 2016 21:57
If I pare down the player object to only used properties then the update time improves, but I feel that that is a poor way to handle the situation.
Julian
@pYr0x
Mar 28 2016 21:57
@RALifeCoach it is difficult to understand your jsbin, because it is huge
do you find out the main problem?
are there to many 2-way binds?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:00
@pYr0x I am working with a huge code base. The problem seems to be that Map is creating obserables for every property whether it is used by the stache template or not
That’s why Justin recommended lazy map.
Julian
@pYr0x
Mar 28 2016 22:01
ok
can you reduce the amount of can.maps?
Thomas Sieverding
@Bajix
Mar 28 2016 22:01
@RALifeCoach You don’t need to use .attr to read properties. You can do foo.bar instead of foo.attr(‘bar’) for properties that don’t have getters
Julian
@pYr0x
Mar 28 2016 22:01
by using the define plugin and type = *
Thomas Sieverding
@Bajix
Mar 28 2016 22:02
If you skip using .attr within a function that tracks bindings, then you skip making those bindings
Thomas Sieverding
@Bajix
Mar 28 2016 22:03
You can use value/Type/type/set and be able to read properties directly
Julian
@pYr0x
Mar 28 2016 22:03
"*" - Prevents the default type coersion of converting Objects to can.Maps and Arrays to can.Lists.
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:03
Yes. I can reduce the number of Map’s. In fact I can get rid of all of them and I don’t see any change in how the code works.
@pYr0x That’s fine, but will my big object - player will change
Julian
@pYr0x
Mar 28 2016 22:04
thats a question?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:05
Yes - how do I stop canjs from creating obserables for unused properties?
Julian
@pYr0x
Mar 28 2016 22:05
as we said
use "type" and "*" for prevent creating a map
and as @Bajix said
If you skip using .attr within a function that tracks bindings, then you skip making those bindings
Thomas Sieverding
@Bajix
Mar 28 2016 22:06
type: ‘*’ prevents the implicit construction of can.List/can.Map when passed an Object/Array instance
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:06
but then what happens when the proparties that are used change?
Becuase there are properties in player that are used and will change
Thomas Sieverding
@Bajix
Mar 28 2016 22:06
You can also do can.__notObserve, push comes to shove
Julian
@pYr0x
Mar 28 2016 22:07
@RALifeCoach not all of the properties will change?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:07
no, not all properties will change
most will, some will remain constant
Julian
@pYr0x
Mar 28 2016 22:07
so these have to find, and prevent from binding
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:08
but MOST properties are never used
Julian
@pYr0x
Mar 28 2016 22:08
and why are they in a map?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:08
out of 100+ properties I may use 30
Thomas Sieverding
@Bajix
Mar 28 2016 22:08
myHelper: function() {
  var scope = this;
  can.__notObserve(function() {
    scope.attr('foo').forEach(function( bar) {
      if (bar.attr('test')) {

      }
    })
  })
}
Technically you could do that as a last ditch effort
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:09
because I do not understand the internals of this product
Julian
@pYr0x
Mar 28 2016 22:09
@RALifeCoach why these properties are stored in a map?
Thomas Sieverding
@Bajix
Mar 28 2016 22:09
But you could also do this.foo and avoid bindings that way
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:09
I do not understand how maps help, I do not understand what a define: Type does
Julian
@pYr0x
Mar 28 2016 22:09
@Bajix nice... good to know
This message was deleted
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:10
@Bajix I do that when referencing properties in code, but I don’t have that option when referencing them in stache
Julian
@pYr0x
Mar 28 2016 22:10
@RALifeCoach you read the docs?
Thomas Sieverding
@Bajix
Mar 28 2016 22:10
myHelper: function() {
  var bar = this.attr('bar'); // binds to {scope} bar
}
myHelper: function() {
  var bar = this.bar; // doesn't bind
}
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:10
Besides, whether I put the properties into a Map or not - CanJS creates observables for ALL properties
Yes I have read, re-read, and re-read the docs over and over again
Thomas Sieverding
@Bajix
Mar 28 2016 22:11
You’re overly concerned with binding in stache files
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:11
I don’t give a damn about binding - I give a damn about performance
Thomas Sieverding
@Bajix
Mar 28 2016 22:11
The truth is that the issue is never the bindings, it’s the time complexity of your functionality
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:11
and folks from canjs said I need to worry about binding
That is what I have to work with
Thomas Sieverding
@Bajix
Mar 28 2016 22:12
If you want to optimize performance, then utilize more computes as a means to prevent unnecessary change events
Julian
@pYr0x
Mar 28 2016 22:12
@Bajix is right
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:13

From @justinbmeyer : "This is because those properties are converted to being observable. There's 135 properties and there's 156 items. 21060 is a lot of data to convert.

LazyMap and LazyList are able to avoid converting all of that and can-define is able to do it faster and you can specify what should be observable and what shouldn’t."

Is Justin wrong?
Thomas Sieverding
@Bajix
Mar 28 2016 22:13
  isAdmin: {
    get: function() {
      var profile = this.attr('profile');

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

      return false
    }
  }
}
Do stuff like this
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:13
Should I ignore all posts from Justin?
Julian
@pYr0x
Mar 28 2016 22:14
@RALifeCoach as is said, reduce the amount of maps
justin in right
Thomas Sieverding
@Bajix
Mar 28 2016 22:14
You can utilize intermediate computes so that things dependent on them don’t unnecessarily re-compute
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:14
He wrote that when I didn’t have so many maps - I just let CanJS do it’s thing
Thomas Sieverding
@Bajix
Mar 28 2016 22:15
If I were to have done this within another compute, then it would be re-computed when profile / tier changed even if the result was still that I’m not an admin
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:15
My player object has 135 properties - Justin said to use Lazy Map - I did and it is faster - except Lazy Map is Broken
Thomas Sieverding
@Bajix
Mar 28 2016 22:16
Give up on LazyMap
Focus on reducing the time complexity of change events
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:16
@pYr0x says Justin is right @Bajix says Justin is wrong
Julian
@pYr0x
Mar 28 2016 22:16
i said, justin is rght with
"This is because those properties are converted to being observable. There's 135 properties and there's 156 items. 21060 is a lot of data to convert."
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:17
If I reduce the size of my player object to ONLY those properties which are used - NO OTHER CHANGES - then the performance improves
So the issue can’t be optimizing change events
Julian
@pYr0x
Mar 28 2016 22:17
??
2 steps
  1. reduce the amount of maps that are created, use "type" in can-define
Thomas Sieverding
@Bajix
Mar 28 2016 22:18
I’m not saying Justin is wrong. I’m just saying that it’s very easy to shy away from computes when they are a very good way to speed things up if you’re able to do so in a way that prevents unnecessary changes
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:18
Let’s back up a bit.
Julian
@pYr0x
Mar 28 2016 22:18
  1. prevent from make bindings as bajix said
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:19
I have an object - player - that has 135 properties and later grows to be close to 1,000 properties
I use very few of those properties
Julian
@pYr0x
Mar 28 2016 22:19
yep
Thomas Sieverding
@Bajix
Mar 28 2016 22:19
Your app struggles with updates though?
Julian
@pYr0x
Mar 28 2016 22:19
you dont to push them all to a can map
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:20
If I remap the player to include only those properties which are used then the update performance improves greatly
But CanJs is supposed to make my life easier - having to write remapping code for every page is NOT making my life easier
Julian
@pYr0x
Mar 28 2016 22:20
is this also a question?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:21
my question remains - Why are unused properties slowing down CanJS?
Julian
@pYr0x
Mar 28 2016 22:21
they are converted to an obervable
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:21
WHY?
Julian
@pYr0x
Mar 28 2016 22:21
thats can.map
can map is used for obvervable
also can.list
Thomas Sieverding
@Bajix
Mar 28 2016 22:22
@RALifeCoach You’re asking the wrong questions. It shouldn’t be why are my properties being converted to observables, it should be why are my innocuous changes triggering so many changes
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:22
Then please give me another option - other than writing remapping code.
Julian
@pYr0x
Mar 28 2016 22:23
@RALifeCoach thats not working that way
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:23
My question is - why is it so damn slow?
Julian
@pYr0x
Mar 28 2016 22:23
we give you a few options
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:23
Having large objects and using very few properties is not an edge use case.
@pYr0x - what are those options?
Julian
@pYr0x
Mar 28 2016 22:24
@RALifeCoach sorry... what about we are talking the last 20 minutes?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:24
So far I have heard lazy map - which I am now being told not to use.
You keep telling me to change how I bind the properties I do use - but that doesn’t make any difference.
Julian
@pYr0x
Mar 28 2016 22:25
what do you not understand what @Bajix and i said?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:25
No.
Julian
@pYr0x
Mar 28 2016 22:25
can you repeat your answers, that may help you?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:25
Please explain as if I am an idiot - which is exactly how I am feeling right now
Julian
@pYr0x
Mar 28 2016 22:26
there a 2 possibility you have:
  1. prevent to make 135 properties with 156 items. 21060 is a lot of data to convert.
  2. prevent from making binding ... Balijx give good examples
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:27
How do I prevent that?
And please be specific.
    • How?
  1. I have tried those options in various ways and they don’t improve performance. Most of the player properties could change.
Julian
@pYr0x
Mar 28 2016 22:31
  1. how do your player map look like?
you use can.define?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:31
There is a sample of the player object in the JSBin. What more do you want to know about it?
Julian
@pYr0x
Mar 28 2016 22:31
// sample data
data = {
this?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:32
yes - within the data = { there is the player object
Julian
@pYr0x
Mar 28 2016 22:32
wwhat is PlayerRowMap
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:33
/*
 * Copyright (c) 2015 Omnigon Communications, LLC. All rights reserved.
 *
 * This software is the confidential and proprietary information of Omnigon Communications, LLC
 * ("Confidential Information"). You shall not disclose such Confidential Information and shall access and use it only
 * in accordance with the terms of the license agreement you entered into with Omnigon Communications, LLC, its
 * subsidiaries, affiliates or authorized licensee. Unless required by applicable law or agreed to in writing, this
 * Confidential Information is provided on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the license agreement for the specific language governing permissions and limitations.
 */

(function($, global) {
    global.pgatour = global.pgatour || {};
    global.pgatour.leaderboard = global.pgatour.leaderboard || {};
    global.pgatour.leaderboard.components = global.pgatour.leaderboard.components || {};
    global.pgatour.leaderboard.components.playerRow = global.pgatour.leaderboard.components.playerRow || {};

    /**
     * Map for player row
     */
    global.pgatour.leaderboard.components.playerRow.PlayerRowMap = can.LazyMap.extend({
        define: {
            highlight: {
                type: 'string'
            },
            index: {
                type: 'number'
            },
            options: {
                Type: global.pgatour.leaderboard.components.playerRow.OptionsMap
            },
            parent: {
                type: 'object'
            },
            pid: {
                type: 'string'
            },
            player: {
                Type: global.pgatour.leaderboard.components.playerRow.PlayerMap
            }
        }
    });
})(jQuery, window);
Julian
@pYr0x
Mar 28 2016 22:33
whats that?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:33
It is my attempt to use can.define
Julian
@pYr0x
Mar 28 2016 22:35
yes but you put the whole data in this map?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:35
it can be simplified to be
    global.pgatour.leaderboard.components.playerRow.PlayerRowMap = can.Map.extend({
        define: {
            highlight: {
                type: 'string'
            },
            index: {
                type: '*'
            },
            options: {
                Type: global.pgatour.leaderboard.components.playerRow.OptionsMap
            },
            parent: {
                type: '*'
            },
            pid: {
                type: '*'
            },
            player: {
                Type: global.pgatour.leaderboard.components.playerRow.PlayerMap
            }
        }
    });
You asked if I put the whole data into the map. Yes. Where else would I put it?
Julian
@pYr0x
Mar 28 2016 22:36
why not putting the data inside PlayerRowMap that you only need?
like these define properties
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:36
Because I don’t want to have to write remapping code for every template in my system.
Julian
@pYr0x
Mar 28 2016 22:37
maybe you can test it with one
and see if this can be a solution
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:37
I have tested it and yes it is much faster, at least on updating
updating went from 6 seconds to .6 seconds
Julian
@pYr0x
Mar 28 2016 22:38
ok so the main question is, how can you reduce the amount of maps, but put all data inside
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:38
initial load only improved slightly
Yes.
Thomas Sieverding
@Bajix
Mar 28 2016 22:39
Teach him about can.Model stores. Utilzing can.Model.models/can.Model.models, especially in conjunction w/ can.Model.parseModel is a good way to allow massive updates of deeply nested data without triggering unnecessary change events
Kevin Phillips
@phillipskevin
Mar 28 2016 22:40
do you have type: ‘*’ mapping in global.pgatour.leaderboard.components.playerRow.PlayerMap also?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:40
I cannot use can.Model as the ajax requests are happening in a completely different module
No I do not have ‘*’ in PlayerMap
Julian
@pYr0x
Mar 28 2016 22:41
@RALifeCoach all properties you dont use, use type = *
Thomas Sieverding
@Bajix
Mar 28 2016 22:41
define([
  'can',
  'config',
  './config',
  'user/model'
], function( can, config, Config, User ) {
  var Channel = can.Model.extend('Channel', {
    id: '_id',
    resource: config.hosts.api + '/channels',
    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;
    },
    setup: function() {

      function makeHandler( endpoint ) {
        return function( key, users ) {
          var data = {};

          data[key] = users;

          return can.ajax({
            url: can.sub(config.hosts.api + endpoint, this),
            type: 'PUT',
            data: data,
            xhrFields: {
              withCredentials: true
            }
          }).then(function( data ) {
            return Channel.model(data);
          });
        };
      };

      this.prototype.addToSet = makeHandler('/channels/{_id}/push');

      this.prototype.pullAll = makeHandler('/channels/{_id}/pull');

      return can.Model.setup.apply(this, arguments);
    }
  }, {
    define: {
      __v: {
        serialize: false,
        value: 0,
        type: 'number'
      },
      name: {
        type: 'string'
      },
      topic: {
        type: 'string'
      },
      owner: {
        serialize: false,
        Type: User
      },
      moderators: {
        value: Array,
        serialize: false,
        Type: User.List
      },
      bannedUsers: {
        value: Array,
        serialize: false,
        Type: User.List
      },
      bootedUsers: {
        value: Array,
        serialize: false,
        Type: User.List
      },
      url: {
        type: 'string'
      },
      avatar: {
        type: 'string',
        serialize: function( val ) {
          if (val && val.indexOf(config.hosts.chat) === 0) {
            return val.slice(config.hosts.chat.length);
          }

          return val;
        },
        set: function( val ) {
          if (val.indexOf('/') === 0) {
            return config.hosts.chat + val;
          }

          return val;
        },
        value: '/assets/channel/images/avatar.png'
      },
      config: {
        value: Object,
        Type: Config
      },
      userCount: {
        serialize: false,
        value: 0,
        type: 'number'
      },
      guestCount: {
        serialize: false,
        value: 0,
        type: 'number'
      },
      createdAt: {
        value: Date,
        serialize: false,
        type: 'date'
      },
      updatedAt: {
        value: Date,
        serialize: false,
        type: 'date'
      },
      lastMessageAt: {
        value: Date,
        serialize: false,
        type: 'date'
      }
    }
  });

  return Channel;
});
This is what my setup looks like. Each property is utilizing type/value/serialization
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:43
@Bajix that is within a Model and the Model is handling ajax requests. In the code I am working with the ajax requests are being handled outside of CanJS
Thomas Sieverding
@Bajix
Mar 28 2016 22:43
I’m using parseModel + User.models/User.model such that I can update a channel w/out trigger change events on channel.owner, channel.moderators, channel.bannedUsers, channel.bootedUsers
@RALifeCoach It doesn’t matter where the AJAX requests are handled
Julian
@pYr0x
Mar 28 2016 22:43
you can do that in can.map also (utilizing type/value/serialization)
Thomas Sieverding
@Bajix
Mar 28 2016 22:44
@pYr0x You can’t actually do that entirely - you need the model/models call within parseModels to get the full effect
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:44
do I make any other changes other than type: ‘*’ to my maps?
Julian
@pYr0x
Mar 28 2016 22:44
nothing else, i can remeber
Thomas Sieverding
@Bajix
Mar 28 2016 22:45
@RALifeCoach Instead of using myAjaxRequest().then(function( data ) { new Foo.List()… }), simply replace the constructor call with Foo.models/Foo.model
It really doesn’t matter where the AJAX happens
If you do this right, it’ll recursively call parseModels/models, and you won’t get unnecessary change events, nor need to reconstruct the whole data structure
Julian
@pYr0x
Mar 28 2016 22:47
also a good @Bajix
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:47
I will try @pYr0x suggestion first - setting properties I don’t need to be type: ‘*’
Julian
@pYr0x
Mar 28 2016 22:48
@Bajix answer is the hardcore version ;)
@RALifeCoach and remove lazymap
dont think it is bullet proof
Thomas Sieverding
@Bajix
Mar 28 2016 22:50
@RALifeCoach The type: * recommendation only applies to areas that would use the Type converter otherwise
can.List, can.Map
You should absolutely use type: ‘number’, type: ‘boolean’, type: ‘string’, type: ‘date’ under all scenarios
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:51
so it it doesn’t help on type: ‘string’?
Kevin Phillips
@phillipskevin
Mar 28 2016 22:52
type: ‘string’ will still be observable
Thomas Sieverding
@Bajix
Mar 28 2016 22:52
The only way that helps is if it prevents the construction of unnecessary can.Map/can.List instances. Again though, I would strongly recommend using parseModels+can.Model.models as an alternative, or otherwise utilize intermediate computes to “funnel” change events
@phillipskevin Yes, but as would type: ‘*’- he’s just trying to speed up the construction of instances
Julian
@pYr0x
Mar 28 2016 22:53
@Bajix what are you meaning by "The type: * recommendation only applies to areas that would use the Type converter otherwise can.List, can.Map"
Thomas Sieverding
@Bajix
Mar 28 2016 22:54
@pYr0x The time complexity of using type to convert primitives & dates is negligable
Julian
@pYr0x
Mar 28 2016 22:55
yes but if he is using type = * a object or an array will not convert to a map
Thomas Sieverding
@Bajix
Mar 28 2016 22:55
The only way type: ‘*’ would ever be performant is if it prevents the implicit construction of can.List/can.Map when passed an Object/Array instance
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:55
I haven’t finished all of the changes, but using ‘*’ on Type’s is not showing much promise
Thomas Sieverding
@Bajix
Mar 28 2016 22:56
As much is to be expected
Julian
@pYr0x
Mar 28 2016 22:56
@Bajix yes.. and i thought he had much nested objects?
data = {
  "highlight":"highlight-undefined",
  "index":0,
  "mediaContent":{},
  "options": {
    "currentRound":1,
    "flagsResourcesUrl":"/pic/flags/24x24/",
    "format":"stroke",
    "hideStandings":false,
    "isActive":true,
    "isFinals":true,
    "isInMyLb":false,
    "isMyLb":false,
    "isSchwabcupMoneyRank":false,
    "isProAm":true,
    "multiCourse":true,
    "myLbPlayerSponsor":"http://i.site.com/image/sponsor-white.png",
    "ocqsLogo":"",
    "ocqsMyLbLogo":"",
    "playerSponsor":"http://i.site.com/image/sponsor-black.png",
    "profilesURL":"/content/players/player.26758.html",
    "scorecardsURL":"/content/site/players/player.26758.html/scorecards/r493",
    "scoringType":3,
    "showSponsorLogo":true,
    "sponsorName":"sponsor",
    "tourCode":"r",
    "tournamentCode":"r493"
  },
  "pid":"11111",
  "player":{
    "debug":{
      "found_in_setup_file":true
    },
    "player_id":"11111",
    "player_bio":{
      "is_amateur":false,
      "first_name":"XXXXX",
      "short_name":"D",
      "last_name":"YYYYY",
      "country":"CAN",
      "is_member":true
    },
    "current_position":"T1",
    "start_position":"",
    "status":"active",
    "thru":9,
    "start_hole":10,
    "course_id":"776",
    "current_round":1,
    "course_hole":18,
    "today":-4,
    "total":-4,
    "total_strokes":31,
    "rounds":[
      {
        "round_number":1,
        "strokes":null,
        "tee_time":"2015-11-19T09:00:00"
      },
      {
        "round_number":2,
        "strokes":null,
        "tee_time":"2015-11-20T10:00:00"
      },
      {
        "round_number":3,
        "strokes":null,
        "tee_time":null
      },
      {
        "round_number":4,
        "strokes":null,
        "tee_time":null
      }
    ],
    "rankings":{
      "cup_points":82,
      "cup_rank":"77",
      "cup_trailing":794,
      "projected_cup_points_total":582,
      "projected_cup_points_event":500,
      "projected_cup_rank":"5",
      "projected_money_total":11,
      "projected_money_event":10,
      "projected_money_rank":"8",
      "priority_proj_rank":"",
      "priority_proj_sort":null,
      "priority_start_rank":"",
      "priority_start_sort":null,
      "priority_seed":null,
      "schwab_start_rank":"",
      "schwab_proj_rank":"",
      "money_start_rank":"84",
      "money_proj_rank":"8",
      "top25_seed":null,
      "start_rank":"",
      "proj_rank":"",
      "proj_sort":null
    },
    "group_id":"14",
    "sortOrder":0,
    "statsToShow":[],
    "course":{
      "course_id":"776",
      "course_code":"SS",
      "course_name":"Resort (SSSe)",
      "is_host":true,
      "par_in":"35",
      "par_out":"35",
      "par_total":"70",
      "distance_in":11,
      "distance_out":10,
      "distance_total":23
    },
    "totalStrokes":0,
    "parPerformance":{
      "moreBogey":0,
      "doubleBogey":0,
      "bogey":0,
      "par":0,
      "birdie":0,
      "eagle":0,
      "doubleEagle":0,
      "total":0,
      "moreBogeyPercent":null,
      "doubleBogeyPercent":null,
      "bogeyPercent":null,
      "birdiePercent":null,
      "eaglePercent":null,
      "doubleEaglePercent":null,
      "parPercent":null
    },
    "strokesOut":0,
    "strokesIn":0,
    "ocqs":false,
    "sponsors":[
      "sponsor"
    ],
    "movement":"--",
    "wasUpdated":true
  },
  "rounds":[1,2,3,4]
};
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:59
That is better
Julian
@pYr0x
Mar 28 2016 22:59
@phillipskevin a string type is observable ? https://github.com/canjs/canjs/blob/master/map/define/define.js#L231
Thomas Sieverding
@Bajix
Mar 28 2016 22:59
Really your options are 1: prevent changes & 2: prevent bindings. You accomplish the first by using more computes rather than less in order to prevent changes that re-compute into the same value from trigger re-computing of computes dependent on them. I gave the example earlier of using isAdmin instead of binding to profile/profile.tier - doing so would prevent a non-admin logging in from triggering the re-compute of a other computes dependent on knowing whether the user is an admin
Christopher Oliphant
@RALifeCoach
Mar 28 2016 22:59
I am down to 1.6 seconds for update
Thomas Sieverding
@Bajix
Mar 28 2016 23:00
The second way to accomplish prevent changes is to be smarter about merging properties, which was what I was talking about when I made the case for using parseModel + model
Julian
@pYr0x
Mar 28 2016 23:00
@Bajix got the points...!
Christopher Oliphant
@RALifeCoach
Mar 28 2016 23:02
is there a way to update all base properties in a single command?
Julian
@pYr0x
Mar 28 2016 23:02
dont understand
what do you mean update?
Christopher Oliphant
@RALifeCoach
Mar 28 2016 23:02
right now I am using this.playerRowMap.attr(‘prop1’, data.prop1);
Julian
@pYr0x
Mar 28 2016 23:02
what are base properties?
Thomas Sieverding
@Bajix
Mar 28 2016 23:03
Also, re: 1, you can use computes to lower the number of bindings. For example, a template that uses a helper 100x that binds to 6 computes would result in 600 bindings, whereas the same template that uses a helper that binds to a compute of those 6 bindings would result in your template only making 100 bindings
Christopher Oliphant
@RALifeCoach
Mar 28 2016 23:03
and so on for properties 2, 3, and 4.
Kevin Phillips
@phillipskevin
Mar 28 2016 23:03
you can pass an object to attr
Julian
@pYr0x
Mar 28 2016 23:03
// set and merge multiple properties:
people.attr({
a: 'Alice',
b: 'Bob'
});
Christopher Oliphant
@RALifeCoach
Mar 28 2016 23:03
@Bajix I have already moved all my calculated fields outside of the map and set them before loading the map.
Kevin Phillips
@phillipskevin
Mar 28 2016 23:03
this.playerRowMap.attr(data);
Thomas Sieverding
@Bajix
Mar 28 2016 23:03
As you can see, computes actually are a way to improve performance, and shouldn’t be shyed away from
Julian
@pYr0x
Mar 28 2016 23:04
// set and merge multiple properties:
people.attr({
    a: 'Alice',
    b: 'Bob'
});
Christopher Oliphant
@RALifeCoach
Mar 28 2016 23:04
thanks
Julian
@pYr0x
Mar 28 2016 23:04
you really read the docs?
Thomas Sieverding
@Bajix
Mar 28 2016 23:04
re: merging multiple props, that syntax is the same as using can.batch.start() / can.batch.stop()
Christopher Oliphant
@RALifeCoach
Mar 28 2016 23:05
I have, and I remember that now, but that are a lot of docs.
Thomas Sieverding
@Bajix
Mar 28 2016 23:06
When I was referring to was how to take people.attr({ friends: [] }), and making it instead do People.model({ _id: ‘me’, friends: […]}), then letting parseModels do People.models(friends) such that I’m recycling existing instances
Julian
@pYr0x
Mar 28 2016 23:06
@Bajix see performance improvemnts in setting up computes
nice :smile:
Christopher Oliphant
@RALifeCoach
Mar 28 2016 23:08
I have tried the first suggestion, converting Type: XXX to type: ‘*’ where the object isn’t used within the model. That halved the response time for updating, but did little to the iniital load time.
Still too slow.
I am now ready to try @Bajix idea of can.Model
I will go back and re-read his earlier posts to see how to make it work.
Thomas Sieverding
@Bajix
Mar 28 2016 23:09
Also, the time complexity of critical functions really matters
@RALifeCoach The only way you can use the can.Model approach is if your data has ID's
Julian
@pYr0x
Mar 28 2016 23:11
i think @Bajix gave you good answers..
i have to go now
Christopher Oliphant
@RALifeCoach
Mar 28 2016 23:11
@pYr0x thanks for your time and patience
@Bajix there is only one row of data in my model and there are fields I could use as id. Does the id field need to be called _id?
Thomas Sieverding
@Bajix
Mar 28 2016 23:13
No, it can be any property
I use _id because my data is backed by MongoDB
Christopher Oliphant
@RALifeCoach
Mar 28 2016 23:51
@Bajix you still there?
Thomas Sieverding
@Bajix
Mar 28 2016 23:51
Yes
Christopher Oliphant
@RALifeCoach
Mar 28 2016 23:52
I have completed my attempt at a model. It’s close, but not right.
Can you take a look? (It’s 240 lines long, not sure how to share it with you.)
Thomas Sieverding
@Bajix
Mar 28 2016 23:53
Paste the updated link, and I’ll look at it in an hour
Or paste in an hour
Your call
Christopher Oliphant
@RALifeCoach
Mar 28 2016 23:56
Here is the new JSBin
I am updating it now
Thomas Sieverding
@Bajix
Mar 28 2016 23:57
type: ‘object’ isn’t valid
Use type: ‘*’ to avoid converting