SlikGrid 虚拟滚动 - 巨大的数据集

发布于 2024-11-30 19:58:37 字数 4944 浏览 1 评论 0原文

我能够扩展Ajax加载示例以适合我的要求。

在当前的实现中,slick.remotemodel.js 中的加载器有一个名为 data 的变量,它是一个 javascript 对象数组。这个数组是网格的数据源。随着我们不断滚动,虽然 DOM 只有呈现的行的页面大小,但 javascript 数组不断增长。

javascript 对象的大小上限是多少?是否有可能内存不足?假设我的数据集约为 125000 行,多列约为 10。我意识到可能需要更多信息来定义数据集的大小,但是根据上述信息,有人可以提供一些输入吗?

为了处理上述情况,我更新了代码。请参阅我的编辑。如果我遗漏了什么,请告诉我。

编辑:我的解决方案是在 onsuccess 方法中调用 clear 方法,以确保数据数组只有 PAGESIZE # 个项目。

(function ($) {
    /***
    * Ajax loading example which is an extension
    * of the http://mleibman.github.com/SlickGrid/examples/example6-ajax-loading.html
    * example.
    */
    function RemoteModel() {
        // private

        var fromPage = 0; 
        var rows = 0; 

        var PAGESIZE = 250; 
        var data = { length: 0 };
        var h_request = null;
        var req = null; // ajax request

        // events
        var onDataLoading = new Slick.Event();
        var onDataLoaded = new Slick.Event();


        function init() {
        }


        function isDataLoaded(from, to) {
            for (var i = from; i <= to; i++) {
                if (data[i] == undefined || data[i] == null)
                    return false;
            }

            return true;
        }


        function clear() {
            for (var key in data) {
                delete data[key];
            }
            data.length = 0;
        }


        function ensureData(from, to) {

            if (req) {
                req.abort();

                for (var i = req.fromPage; i <= req.toPage; i++)
                    data[i * PAGESIZE] = undefined;
            }

            if (from < 0)
                from = 0;

            fromPage = Math.floor(from / PAGESIZE);
            var toPage = Math.floor(to / PAGESIZE);

            while (data[fromPage * PAGESIZE] !== undefined && fromPage < toPage)
                fromPage++;

            while (data[toPage * PAGESIZE] !== undefined && fromPage < toPage)
                toPage--;

            rows = (((toPage - fromPage) * PAGESIZE) + PAGESIZE);

            if (fromPage > toPage || ((fromPage == toPage) && data[fromPage * PAGESIZE] !== undefined)) {

                // TODO:  look-ahead
                return;
            }

            var url = "" ; // IMPORTANT : you should set this to your url which returns the data

            if (h_request != null) {
                clearTimeout(h_request);
            }

            h_request = setTimeout(function () {

                for (var i = fromPage; i <= toPage; i++)
                    data[i * PAGESIZE] = null; // null indicates a 'requested but not available yet'

                onDataLoading.notify({ from: from, to: to });

                req = $.ajax({
                    url: url,
                    dataType: 'json',
                    success: function (response) {
                        onSuccess(response);
                    },
                    error: function () {
                        onError(fromPage, toPage);
                    }
                });


                req.fromPage = fromPage;
                req.toPage = toPage;

            }, 100);
        }


        function onError(fromPage, toPage) {
            alert("error loading pages " + fromPage + " to " + toPage);
        }

        function onSuccess(response) {

            //Solution to keep the data array bounded to pagesize: Call the clear method to have only PAGESIZE elements in the data array at any given point
            clear(); 

        //The visisble # of rows in the viewport could be only ~20 but
           // i'm populating PageSIZE which acts like the client-side cache, in my case 250,
      // so that I avoid too many server hops
            var from = fromPage * PAGESIZE, to = from + PAGESIZE;

            data.length = response.count;

            for (var i = 0; i < response.Fields.length; i++) {
                data[from + i] = response.Fields[i];
                data[from + i].index = from + i;
            }

            req = null;

            onDataLoaded.notify({ from: from, to: to });
        }


        function reloadData(from, to) {
            for (var i = from; i <= to; i++)
                delete data[i];

            ensureData(from, to);
        }


        init();

        return {
            // properties
            "data": data,

            // methods
            "clear": clear,
            "isDataLoaded": isDataLoaded,
            "ensureData": ensureData,
            "reloadData": reloadData,

            // events
            "onDataLoading": onDataLoading,
            "onDataLoaded": onDataLoaded
        };
    }

    // Slick.Data.RemoteModel
    $.extend(true, window, { Slick: { Data: { RemoteModel: RemoteModel}} });
})(jQuery);
enter code here

谢谢

I was able to extend the Ajax-Loading Example to suit my requirement.

In the current implementation, the loader in slick.remotemodel.js has a variable called data which is an array of javascript objects. This array is the datasource for the grid.As we keep scrolling, although the DOM has only page size of rows rendered, the javascript array keeps growing.

What is the upper limit of size of javascript object ? Is there a possibility of running out of memory ? Lets say my data set is in the order of ~125000 rows with multiple columns ~10. I realize more information might be required to define the size of the dataset but with the above info, can somebody provide some inputs ?

To handle the above scenarios, I updated the code. Please see my edit. Please let me know if I'm missing anything.

Edit: My solution was to call the clear method in onsuccess method to make sure the data array has only PAGESIZE # of items.

(function ($) {
    /***
    * Ajax loading example which is an extension
    * of the http://mleibman.github.com/SlickGrid/examples/example6-ajax-loading.html
    * example.
    */
    function RemoteModel() {
        // private

        var fromPage = 0; 
        var rows = 0; 

        var PAGESIZE = 250; 
        var data = { length: 0 };
        var h_request = null;
        var req = null; // ajax request

        // events
        var onDataLoading = new Slick.Event();
        var onDataLoaded = new Slick.Event();


        function init() {
        }


        function isDataLoaded(from, to) {
            for (var i = from; i <= to; i++) {
                if (data[i] == undefined || data[i] == null)
                    return false;
            }

            return true;
        }


        function clear() {
            for (var key in data) {
                delete data[key];
            }
            data.length = 0;
        }


        function ensureData(from, to) {

            if (req) {
                req.abort();

                for (var i = req.fromPage; i <= req.toPage; i++)
                    data[i * PAGESIZE] = undefined;
            }

            if (from < 0)
                from = 0;

            fromPage = Math.floor(from / PAGESIZE);
            var toPage = Math.floor(to / PAGESIZE);

            while (data[fromPage * PAGESIZE] !== undefined && fromPage < toPage)
                fromPage++;

            while (data[toPage * PAGESIZE] !== undefined && fromPage < toPage)
                toPage--;

            rows = (((toPage - fromPage) * PAGESIZE) + PAGESIZE);

            if (fromPage > toPage || ((fromPage == toPage) && data[fromPage * PAGESIZE] !== undefined)) {

                // TODO:  look-ahead
                return;
            }

            var url = "" ; // IMPORTANT : you should set this to your url which returns the data

            if (h_request != null) {
                clearTimeout(h_request);
            }

            h_request = setTimeout(function () {

                for (var i = fromPage; i <= toPage; i++)
                    data[i * PAGESIZE] = null; // null indicates a 'requested but not available yet'

                onDataLoading.notify({ from: from, to: to });

                req = $.ajax({
                    url: url,
                    dataType: 'json',
                    success: function (response) {
                        onSuccess(response);
                    },
                    error: function () {
                        onError(fromPage, toPage);
                    }
                });


                req.fromPage = fromPage;
                req.toPage = toPage;

            }, 100);
        }


        function onError(fromPage, toPage) {
            alert("error loading pages " + fromPage + " to " + toPage);
        }

        function onSuccess(response) {

            //Solution to keep the data array bounded to pagesize: Call the clear method to have only PAGESIZE elements in the data array at any given point
            clear(); 

        //The visisble # of rows in the viewport could be only ~20 but
           // i'm populating PageSIZE which acts like the client-side cache, in my case 250,
      // so that I avoid too many server hops
            var from = fromPage * PAGESIZE, to = from + PAGESIZE;

            data.length = response.count;

            for (var i = 0; i < response.Fields.length; i++) {
                data[from + i] = response.Fields[i];
                data[from + i].index = from + i;
            }

            req = null;

            onDataLoaded.notify({ from: from, to: to });
        }


        function reloadData(from, to) {
            for (var i = from; i <= to; i++)
                delete data[i];

            ensureData(from, to);
        }


        init();

        return {
            // properties
            "data": data,

            // methods
            "clear": clear,
            "isDataLoaded": isDataLoaded,
            "ensureData": ensureData,
            "reloadData": reloadData,

            // events
            "onDataLoading": onDataLoading,
            "onDataLoaded": onDataLoaded
        };
    }

    // Slick.Data.RemoteModel
    $.extend(true, window, { Slick: { Data: { RemoteModel: RemoteModel}} });
})(jQuery);
enter code here

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

失而复得 2024-12-07 19:58:37

我的解决方案是在 onsuccess 方法中调用 clear 方法,以确保数据数组只有 PAGESIZE # 个项目。这只会将所需的数据保留在 javascript 对象数组中,其他所有内容都应设置为未定义。

My solution was to call the clear method in onsuccess method to make sure the data array has only PAGESIZE # of items. This will only keep data in the javascript object array which is required and everything else should be set to undefined.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文