NodeJs 实现 jsonp 方式获取xml数据

     NodeJs未诞生前,如果一个前端程序员想要通过纯粹的js来实现跨域获取xml数据是想都不敢想的,因为浏览器的同源安全策略拒绝端对端的数据访问, 通常我们需要借助后端程序通过代理中转来实现。

     随着NodeJs的问世,前端程序员可以做以往很多由php,java等才能实现的后端功能,最直接简单的就是我们今天所要探讨的jsonp。

     要实现今天的主题,我们先来掌握一下nodejs的基本运行机制。nodejs 分为程序类和服务类, 程序类是指不需要创建服务器而实现的功能,比如抓取一个页面的内容保存到你自己的开发机上,供其它场景使用。此时,就可以通过http模块的Get方法去请求网页内容,即要实现的读取数据源;然后通过引入文件模块fs进行写操作,写抓取到的内容到自己想要的地方。写nodejs程序的时候,完全符合按需加载的规范。要实现上述两个功能,只要加载引入http模块和fs模块即可。如下代码:


var http = require('http');
var fs = require('fs');
http.get('http://*****/xml/e_gamedata.xml',function(html){
     var cont='';
     html.on('data',function(content){
         cont += content.toString('utf-8');
     })
     html.on('end',function(){
         fs.writeFile('message.xml', cont, function (err) {
             if (err) throw err;
             console.log('It\'s saved!');
         });
     })
});

在此程序中, http.get的回调中,有两个重要的方法需要掌握,一个是接收数据的data,表示有数据接收后要执行的操作,用法就是html.on('data',function(){ do something }); 另一个方法是end,是指此get 数据读取完毕后要执行的操作。ok,运行 node 测试一下吧!如果成功,控制台会告诉你"it's saved"。 是不是很简单呢!


     好了我们已经实现了简单的读写操作,那么我们如何实现跨域jsonp方案呢?其实原理跟php等后端程序的实现方案一样,通过nodejs来搭建http服务器作为中转。不过这个是前端的一大荣誉,终于可以用自己的语言来写服务类应用了。首先用nodejs来创建http服务器吧!相当简单的一句话 http.createServer(function(req, res){ so something }); 我们通过这句就创建了一个http的服务器,接下来的步骤就是如何跟前端进行通信了。


    前面已经说了和php实现jsonp的方案一样,nodejs服务端通过和前端双方约定信任,即callback参数,来进行通信。  前端通过 getJSON('url+callback=?',function(data){ console.log(data) })向nodejs服务端发送请求,同时发送通信信任参数callback。服务端接到请求后,以接收到的callback参数回传,同时返回数据到前端。如果双方验证信任参数callback一致,就完成了的jsonp通信方案。


    服务端解析请求需要用到url模块,生成json格式数据需要用到JSON.stringify()方法,具体代码:


var http = require('http');
var urllib = require('url');
var port = 10011;
var jsondata = [{name:'ang xiao',age:'30',school:'xue feng',score:'98'},{name:'da long',age:'20',school:'aaa',score:'88'}];
http.createServer(function(req, res){
    var params = urllib.parse(req.url, true);
    var str =  params.query.callback + '(' + JSON.stringify(astr) + ')';//jsonp
    res.end(str);
}).listen(port, function(){
    console.log('server is listening on port ' + port); 
})

   ok,node一下,前端通过getJSON访问此服务地址看看接收到的数据吧!getJSON('http://**.**.**.**:10011?callback=?',function(data){ console.log(data) });

    到此,我们已经实现了get抓取xml数据和jsonp方案。把这两者结合起来就是实现我们的主题功能。“NodeJs 实现 jsonp 方式获取xml数据”;


    最后一步的难点在于我们如何在后端实现xml转换为json,读取xml数据有很多第三方的模块,如xmlreader,xml-digester;我自己用了xmlreader来实现。 安装这个第三方模块 npm install xmlreader, 然后引入此模块。用法为:xmlreader.read(xmlstr,function(errors, response){if(null !== errors ){console.log('errors');return;} dosometing });

xmlreader read后,可以在控制台打印一下回调 查看回调的一些属性和方法。其实xmlreader是把读取的数据转换为了一个objecet, 你就可以a.b.c的方法去取到你想要的数据。其中一个重要的方法是each,相当于一个数组。


{ text: [Function],
  DOCUMENT:
   { attributes: [Function],
     parent: [Function],
     count: [Function],
     at: [Function],
     each: [Function],
     text: [Function],
     funny:
      { attributes: [Function],
        parent: [Function],
        count: [Function],
        at: [Function],
        each: [Function],
        text: [Function],
        game: [Object] },
     competitive:
      { attributes: [Function],
        parent: [Function],
        count: [Function],
        at: [Function],
        each: [Function],
        text: [Function],
        game: [Object] } } }



你要做的就是操作拼装你需要的数据,然后进行json转换,再然后返回到前端。 ok,看到此,我默认你已了解了实现方案的原理。上代码:


var http = require('http');
var xmlreader = require('xmlreader');
var urllib = require('url');
var port = 10011;
var xmlstr = '';
var jsondata = {};
http.get('http://*******/xml/e_gamedata.xml', function (html) {
    html.on('data',function (content) {
        xmlstr += content;
    })
})
http.createServer(function(req,res){
    xmlreader.read(xmlstr, function (errors, response) {
        if (null !== errors) {
            console.log('errors');
            return;
        }
        var oSourceFunny=[],oSourceCompeti=[];
        response.DOCUMENT.funny.game.each(function (i, item) {
            oSourceFunny.push({
                name : item.name.text(),
                intro : item.intro.text(),
                score : item.score.text(),
                type : item.type.text(),
                property : item.property.text(),
                feature : item.feature.text(),
                img : item.img.text(),
                link : item.link.text(),
                from : item.from.text()
            });
        });
        response.DOCUMENT.competitive.game.each(function (i, item) {
            oSourceCompeti.push({
                name : item.name.text(),
                type : item.type.text(),
                img : item.img.text(),
                link : item.link.text(),
                from : item.from.text()
            });
        });
        jsondata = {oSourceFunny:JSON.stringify(oSourceFunny),oSourceCompeti:JSON.stringify(oSourceCompeti)};
        var params = urllib.parse(req.url, true);
        if (params.query && params.query.callback) {
            var calldata = params.query.callback + '(' + JSON.stringify(jsondata) + ')'; //jsonp
            res.end(calldata);
        } else {
            res.end(jsondata);//普通的json
        }
    })
}).listen(port,function(){
    console.log('this server run at'+port);
})



至此,一整套完整的前端获取解析xml数据的jsonp方案实现了。 

要了解nodejs http和url、fs等模块使用方法,请查阅nodejs官网接口文档。http://nodejs.org/api/ 

想要了解 xml-digester使用方法,请参阅 http://jackie198512.blog.163.com/blog/static/9607024201391823011748/ 。 


据称 xml-digester  可以直接将文档转换为json,个人没有用过,如果真如所说,倒是节省了很多后台的读取操作,那真正是终极完美方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值