Debugging: library sort works on reload

I’ve created a tiny library for doing some data handling, which I use by importing to Observable: it’s nothing new and not fancy, but it has amused me and does what I need with a syntax that suits me.

Everything works except for one bit of functionality: the sort() method is used to sort a table by one or more columns. In Observable, this does not seem to work (resulting data is unsorted), except if I reload the notebook, then the result is correct. I suspect I’m falling foul of the execution model, as the same code runs correctly when running as standalone JS in Node. I can’t work out a strategy for debugging this one.

I’ve created a minimal failing example notebook here. You can see the issue by changing the column name to sort, which is passed as an argument to dec(), or change the sort order to increasing by calling inc() instead of dec().

Thanks in advance for any help!

Have you tried multiple successive calls in Node and checked the end result?

If I follow your question, I can do successive calls like

let res = model().sort().inc('nation').end().data(athletes);
res = model().sort().inc('nation').end().data(res);
res = model().sort().inc('nation').end().data(res);

and this works in Node.

You’ll want data(athletes) though in all calls?

Yes so similarly,

let res = model().sort().inc('nation').end().data(athletes);
res = model().sort().inc('nation').end().data(athletes);
res = model().sort().inc('nation').end().data(athletes);

works in Node.

I’m not sure what your example is supposed to demonstrate. You sort in the same way every time.

My guess would be that you store a reference to the first passed in array and only operate on that one. Have you tried it with different arrays, or by calling slice?

let res = model().sort().inc('nation').end().data(athletes.slice());
res = model().sort().inc('nation').end().data(athletes.slice());
res = model().sort().inc('nation').end().data(athletes.slice());

Also works in Node.

Sorry I’m not sure I am sure what my example should demonstrate. Perhaps I should come at this a different way: for a single sort performed once, what is Observable doing extra/repeatedly that a single statetment in Node is not? If I understood that more perhaps I could test the differences better.

Thank you

Have a look at this test:

{
  const data = [{a: 1, b: 3}, {a: 2, b: 2}, {a: 3, b: 1}];
  const sort = (column, dir, data) => mt.model()
    .sort()[dir](column).end()
    .data(data.slice())
    .map(d => d[column]);
  
  const results = [];
  
  results.push( sort("a", "dec", data) );
  results.push( sort("b", "dec", data) );
  return results;
}

Both entries in results should be sorted in descending order, but instead you get:

Array(2) [
  0: Array(3) [3, 2, 1]
  1: Array(3) [1, 2, 3]
]
1 Like

Brilliant thank you this is a helpful test. I should be able to debug now (I hope).

1 Like

I’d recommend to start with some unit tests where you define your expectations. A framework like jest should be fairly easy to set up and get started with.

Thanks for the recommendation: tragically, this package is using jest with all good intentions of test-driven development, and I have unit tests, but clearly not of good enough quality!

Thanks so much for your help: I think I see my problem now. A fairly monumental blunder with prototypes sharing members (!!!), which I can fix.