Advertisement
Guest User

Untitled

a guest
Jul 29th, 2016
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.47 KB | None | 0 0
  1. /**
  2. * Adds a `getAsyncTwin()` method to the prototype of Knockout's ObservableArray
  3. * returning a new ObservableArray that will be a continuous non-instant copy of the original.
  4. * Whenever the original ObservableArray changes, the copy will be populated
  5. * in chunks of a given size and with a given delay between the chunks until it is identical to the original.
  6. *
  7. * Intended to allow rendering the first (visible) part of huge lists faster before all the rest.
  8. *
  9. * Example:
  10. *
  11. * var hugeList = ko.observableArray(someHugeArray),
  12. * hugeListToRender = hugeList.getAsyncTwin({
  13. * chunkSize: 100,
  14. * chunkDelay: 1
  15. * });
  16. *
  17. * <ul data-bind="foreach: hugeListToRender">..</ul>
  18. */
  19. define(['knockout', 'util', 'LOG'], function(ko, util, LOG) {
  20.  
  21. 'use strict';
  22.  
  23. /**
  24. * @param opts (Object)
  25. * - chunkSize (number|function) number of items to copy per update interval OR a function to determine
  26. * the number based on the new total size,
  27. * e.g. function(total){ return (total <= 100) ? 20 : 10 }
  28. * - chunkDelay (number|function) delay in millis between the chunks OR a function to determine the delay
  29. * based on the new total size,
  30. * e.g. function(total){ return (total <= 100) ? 20 : 10 }
  31. */
  32. ko.observableArray.fn.getAsyncTwin = function(opts) {
  33. util.assertObject(opts, 'Invalid options object for observableArray.getAsyncTwin');
  34. if (typeof opts.chunkSize === 'number') {
  35. util.assertNumberInRange(opts.chunkSize, 1, 1000000, 'Illegal chunkSize number for observableArray.getAsyncTwin');
  36. } else {
  37. util.assertFunction(opts.chunkSize, 'Invalid chunkSize option for observableArray.getAsyncTwin');
  38. }
  39. if (typeof opts.chunkDelay === 'number') {
  40. util.assertNumberInRange(opts.chunkDelay, 1, 60000, 'Illegal chunkDelay number for observableArray.getAsyncTwin');
  41. } else {
  42. util.assertFunction(opts.chunkDelay, 'Invalid chunkDelay option for observableArray.getAsyncTwin');
  43. }
  44.  
  45. var sourceObsArray = this,
  46. twinObsArray = ko.observableArray(),
  47. chunkSize = -1, // determined on update start
  48. chunkDelay = -1, // determined on update start
  49. timer = null,
  50. continueUpdate = function(clearArray) {
  51. if (timer) {
  52. clearTimeout(timer);
  53. timer = 0;
  54. }
  55.  
  56. if (clearArray) {
  57. twinObsArray().length = 0;
  58. }
  59.  
  60. var sourceArray = sourceObsArray(),
  61. twinArray = twinObsArray(),
  62. firstItemIndex = twinArray.length,
  63. lastItemIndex = Math.min(firstItemIndex + chunkSize - 1, sourceArray.length - 1);
  64.  
  65. if (firstItemIndex <= lastItemIndex) {
  66. LOG.debug('Adding items %s to %s', firstItemIndex, lastItemIndex);
  67.  
  68. for (var i = firstItemIndex; i<= lastItemIndex; i++) {
  69. twinArray[i] = sourceArray[i];
  70. }
  71.  
  72. if (twinArray.length < sourceArray.length) {
  73. LOG.debug('Scheduling next chunk in %s millis', chunkDelay);
  74. timer = setTimeout(continueUpdate, chunkDelay);
  75. } else {
  76. LOG.debug('asyncTwin complete [total=%s]', twinArray.length);
  77. }
  78.  
  79. } else {
  80. LOG.debug('Empty chunk for asyncTwin#continueUpdate');
  81. }
  82.  
  83. twinObsArray.valueHasMutated();
  84. },
  85. startUpdate = function() {
  86. if (timer) {
  87. clearTimeout(timer);
  88. timer = 0;
  89. }
  90.  
  91. var newSize = sourceObsArray().length;
  92.  
  93. chunkSize = (typeof opts.chunkSize === 'function') ? opts.chunkSize(newSize) : opts.chunkSize;
  94. chunkDelay = (typeof opts.chunkDelay === 'function') ? opts.chunkDelay(newSize) : opts.chunkDelay;
  95.  
  96. LOG.debug('asyncTwin#startUpdate [total=%s|chunkSize=%s|chunkDelay=%s]', newSize, chunkSize, chunkDelay);
  97.  
  98. continueUpdate(true);
  99. };
  100.  
  101. sourceObsArray.subscribe(startUpdate);
  102.  
  103. startUpdate();
  104.  
  105. return twinObsArray;
  106. };
  107.  
  108. return ko;
  109.  
  110. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement