Использовать Web Worker и D3.js для асинхронного генерации графиков?

В настоящее время я работаю над проблемой, которая требует, чтобы мое веб-приложение создавало диаграмму, которая представляет приблизительно 50 тыс. к 60 тыс. точек данных. Он загружается довольно быстро (~ 6 секунд), но мне интересно, можно ли использовать D3.js для генерации графика в Web Worker, а затем передать SVG обратно для загрузки на страницу.

Ответ 1

У веб-рабочих нет доступа DOM, поэтому все, что вы могли бы сделать на этой стороне, было бы создание чего-то, что можно было бы использовать для быстрого создания DOM. Работник мог, например, обрабатывать наборы данных и выполнять все тяжелые вычисления, а затем передавать результат как набор массивов.

Ответ 2

https://github.com/mbostock/d3/commit/43d38773623b52209d2667287a1ae626fb95b0d9

Недавняя сделка Джейсона Дэвиса. Майк Босток говорит, что в будущем код, зависимый от DOM, будет отделен от d3.core, и таким образом вы можете создать собственную сборку d3, которая будет работать с API веб-рабочих.

У меня была та же проблема, когда у меня есть ориентированный на силу граф с большим количеством узлов. Он чувствует себя очень вяло. Я хочу улучшить производительность в некотором роде. Я думаю, что последняя ветвь с phantomJS на сервере node - хорошая идея, но сетевая латентность, вовлеченная в этот подход, разрушит плавное силовое чувство.

Ответ 3

Мне удалось вычислить аккорды и группы макета аккорда с помощью веб-рабочего, выполнив следующие действия:

  • создать пользовательскую сборку d3, которая не имеет зависимости от объекта документа или DOM (см. https://github.com/mbostock/smash/wiki)

  • создать файл веб-рабочего и использовать importScripts для загрузки пользовательской сборки d3

  • активируйте своего работника в коде рендеринга. Я использовал обещание инкапсулировать сообщение с рабочим:

    calculateChords = (padding, matrix) ->
            deferred = $.Deferred()
    
            worker = new Worker("worker.js")
    
            worker.onmessage = (e) ->
                deferred.resolve(e.data.groups, e.data.chords);
    
            worker.postMessage {
                matrix: matrix
            }
    
            deferred.promise()
    

    позже, в функции рендеринга:

    calculateChords(matrix).then (groups, chords) ->
        ...