Problems sorting initial data donejs+mongodb+feathersjs


#1

I have issues sorting the data received by a REST API.

I created a very simple feathersjs project (https://github.com/nriesco/donejs-sorter-problem-api), you’ll need a DB called donejs_sorter_problem_api a collection named demo and this sample data:

{
    "_id" : ObjectId("5a9ca44b75cc838af37e57f4"),
    "name" : "Camila",
    "order" : 10
}, {
    "_id" : ObjectId("5a9ca45b75cc838af37e57f5"),
    "name" : "Antonia",
    "order" : 2
}, {
    "_id" : ObjectId("5a9ca47075cc838af37e57f6"),
    "name" : "Ignacia",
    "order" : 3
}

Then start it using npm start and test it here: http://localhost:4000/demo

Then using a donejs project (https://github.com/nriesco/donejs-sorter-problem) go to the home page and you’ll see the not-sorted elements. You can modify these lines (invert the comments) https://github.com/nriesco/donejs-sorter-problem/blob/master/src/demo/demo.js#L35-L36 and the browser will freeze because it uses 100% cpu (an infinite loop).

I tried not sorting when it was not a DefineMap instance, and when using SSR but no luck at all.

Thanks


#2

I’m betting this will break without ssr, in plain canjs. This is because sort in JS mutates the array. Instead, could you clone the define list and sort the resulting array?

list.get().sort(…)


#3

This is something canjs 4 can warn about. We can see mutations while a compute is evaluating and warn. Are you using 4.0? I can show where to put this warning.


#4

Another idea would be to turn off mutations as side effects within derive entirely. The sort would happen, but would produce no events.


#5

I use canjs 3.

I tried this but shows no results:

sortedElements: {
    get: function() {
      if (this.elements !== undefined) {
        let out = this.elements.map(element => {
          element = new DefineMap({ seal: false }, element);
          // element = Object.assign({}, element);
        });
        return new DefineList(out);
      } else {
        return this.elements;
      }
      // if (platform.isNode) {
      //   return this.elements;
      // } else {
      //   if (this.elements instanceof DefineList) {
      //     // returning this.elements.sort() will cause the browser to freeze (infinite loop)
      //     // return this.elements.sort(sorter);
      //     return this.elements;
      //   } else {
      //     return this.elements;
      //   }
      // }
    }
  },

#6

Discussion here: https://gitter.im/donejs/donejs?at=5ad274153fe1be3704cabfb4

Solution is to clone the data you are modifying as shown in this JSBin: http://jsbin.com/gakenah/edit?html,js,output

  modifiedElements: {
    get: function() {
      if (this.elements !== undefined) {
        var res = this.elements.get().sort(function(a,b){
          return -1;
        });
        return res;
      }
    }
  },

#7

Problem solved, thanks to @justinbmeyer.
I’ve updated https://github.com/nriesco/donejs-sorter-problem
The whole viewmodel looks llike this:

export const ViewModel = DefineMap.extend({
  get myPromise() {
    return DemoModel.getList({});
  },
  elements: {
    get: function(last, set) {
      this.myPromise.then(set);
    }
  },
  sortedElements: {
    get: function() {
      if (this.elements !== undefined) {
        return this.elements.get().sort(sorter);
      }
    }
  },
  modifiedElements: {
    get: function() {
      if (this.elements !== undefined) {
        return this.elements.get().map(element => {
          element.order += ' super!';
          return element;
        });
      }
    }
  },
});

More details here: https://github.com/nriesco/donejs-sorter-problem/blob/master/src/demo/demo.js#L40-L57