在d3.json()之后,Nodejs脚本无法打印?

时间:2015-02-22 21:11:29

标签: node.js d3.js jsdom

编辑:已重写问题以更好地隔离问题。)


我正在编写单个D3js script.js,可以在客户端的Web浏览器和服务器端使用的nodejs中“重新使用”。我取得了一些进展:

  1. 单个d3js script.js确实在客户端和服务器端创建了基本的svg形状。在显示viz的Web浏览器上,在服务器端输出所需的map.svg文件。
  2. 我有一个更复杂的d3js地图制作代码:客户端它就像一个魅力(link
  3. enter image description here

    但是! nodejs调用失败没有错误消息。 xhr d3.json()似乎挂断了等待而没有开始回调:

    mapIt.node.js(服务器端,失败)

    传递变量并运行我:

    $ WIDTH=800 ITEM="world-1e3" node script.node.js
    

    script.node.js的内容:

    var jsdom = require('jsdom');         // npm install jsdom
    var fs    = require('fs');            // natively in nodejs.
    
    jsdom.env(
      "<html><body></body></html>",       // CREATE DOM HOOK
      [ './d3.v3.min.js',             // load assets into window environment (!)
      './topojson.v1.min.js', 
      './queue.v1.min.js', 
      './script.js' ],
    
      function (err, window) {
        /* ***************************************************************** */
        /* Check availability of loaded assets in window scope. ************ */
        console.log(typeof window.mapIt);       // expect: 'function',  because exist in script.js !
        console.log(typeof window.doesntExist); // expect: 'undefined', because doesn't exist anywhere.
        // if all as expected, should work !
    
        /* ***************************************************************** */
        /* COLLECT ENV.VARIABLES ******************************************* */
        var width = process.env.WIDTH,
            target= process.env.ITEM;
    
        /* ***************************************************************** */
        /* D3js FUNCTION *************************************************** */
        var url = "http://rugger-demast.codio.io/output/"+target+"/administrative.topo.json";
        console.log(url);
        console.warn(window.document.URL);
    
        var mapIt = function(width, target){
            console.log("mapIt(): start");
    
            var svg = d3.select('body').append('svg')
                .attr('width', width)
                .attr('height', width/960*500);
            var projection = d3.geo.mercator()
                .scale(100)
                .translate([width / 2, height/2]);
            var path = d3.geo.path()
                .projection(projection);
    
            var url = "http://rugger-demast.codio.io/output/"+target+"/administrative.topo.json";
    
            /* FROM HERE SOMETHING FAILS ********************** */
            d3.json(url, function (error, json) { // from here: NOT fired on server side :(
            if (error) return console.warn(error);
                d3.select("svg").append("g").attr("log","d3.json"); 
                svg.append('path')
                    .datum(topojson.feature(json, json.objects.admin_0))
                        .attr('d', path)
                        .attr('class', 'L0');
            });    
        };
        window.mapIt(width,target);
        /* ***************************************************************** */
        /* SVG PRINT ******************************************************* */
        // better svg header:
        var svgheader = '<?xml version="1.0" encoding="utf-8"?>\n'
        +'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n';
        // printing + timer, to be sure all is ready when printing file:
        setTimeout(
          fs.writeFileSync('map.svg', svgheader + window.d3.select("body").html()) ,
          30000
        );
     }
    );
    

    map.svg(不完整)

    由于没有触发d3.json回调,我得到了不完整的map.svg:

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    <svg width="800" height="416.6666666666667"></svg>
    

    根据map.svg的内容,该脚本首先按预期工作,设置svg widthheight属性,然后d3.json()不起作用,回来永远不会被激怒。没有错误消息。但鉴于脚本停止的地方,似乎查询正在等待。

    注意:

    同样精确的d3js脚本适用于客户端(link)。

    有趣的是,console.warn(window.document.URL)返回file:///data/yug/projects_active/map/script.node.js(纯粹是本地的),而d3.json()xhr请求在http://bl.ocks.org/hugolpz/raw/1c34e14d8b7dd457f802/administrative.topo.json上。

    问题

    如何让请求正常运行?或如何运行nodejs脚本,以便允许查询?

    测试

    试用脚本(Github gist):

    git clone https://gist.github.com/9bdc50271afc49d33e35.git ./map
    cd ./map; npm install
    WIDTH=800 ITEM="world-1e3" node script.node.js
    

    帮助:D3js>API>Requests

1 个答案:

答案 0 :(得分:1)

替换:

setTimeout(
      fs.writeFileSync('map.svg', svgheader + window.d3.select("body").html()) ,
      10000
    );

通过

setTimeout(
      function(){ fs.writeFileSync('map.svg', svgheader + window.d3.select("body").html()) } ,
      10000
    );