Nodejs搭建简单的websocket服务
初入大前端小白们,需要明白的几个概念问题(持续更新)
1, npm install是帮助安装 vue,或React到本地,npm install也可以安装vue,React的开发工具。当然你完全可以像jQuery一样自己找网站下载下来,在页面中引入。
2,没有npm可以使用vue,vue只是一个前端框架。
3,4,node是js的服务执行环境,前端常常借助 node帮助前端实现工程化。很多工具是基于node的,比如说你说的webpack,grunt。
5,webpack,grunt是前端工程化的工具,可以帮助前端完成混淆压缩,校验等工作。
6,7,实战中没用过,请参考官方文档http://cn.vuejs.org/v2/guide/...
8,可以单纯的利用 php+vue或者php+react开发。
9,最后一个问题太大,可以写本书。而且老实讲,一切都需要实战中才能有更深的体会。
最后总结一下:
前端圈所谓得“乱”,一个是近些年前端框架层出不穷,工程化,解决方案越来越多,已经脱离了一般人认为的那个“好单纯好不做作”的前端。就像后端开发有很多工具协作开发一样,前端也需要越来越多的工作完成前端面临巨大的工作量。 前端的行业发展已经不是那种后端在php,jsp中写一些html,前端来写一些css来完成工作的阶段。老实讲,我现在80%的时间在写js。前端已经不是后端开发的最后一步甚至“附属品”,而成为真正意义的“客户端”。复杂度也就慢慢和app等客户端越来越接近。
总的来说,你还是可以按照原先的开发方式来开发自己的应用,当然考虑引进工具一些先进的理念方法来协助开发。node,webpack,vue这些概念不应该成为自己开发中的阻碍,而是在自己在面临一些问题时的利剑。这些概念的学习需要一天一天的来,毕竟一口吃不成个胖子 :)
什么是npm?
从事网站制作的小前端们都知道cdn的概念,也就是在网站制作中如果我们需要jquery或者bootstrap等文件支持的话,就可以通过cdn引入的方式来实现调用。由于node的使用日益广泛,也带动了其组件npm的使用,而npm就是这些jquery以及bootstrap这些文件包的组合管理器。现在只要使用了node环境进行web网站开发,你就可以直接用npm进行调用以前所有的cdn文件了。
什么是webpack?
webpack简单来说就是前端代码资源的包管理工具,他自动整理你的项目结构,结合javascript的模块化组件,机型解析并交给浏览器渲染使用,大大提高前端的开发效率。
什么是vue-cli?它与vue脚手架有什么关系?
其实vue-cli就是vue的脚手架,vue脚手架的作用是用来自动一键生成vue+webpack的项目模版,包括依赖库,免去你手动安装各种插件,寻找各种cdn并一个个引入的麻烦。
什么是node.js?它与vue具体有什么关系?
提到vue就不得不说node了,vue作为一个前端框架技术,主要负责了数据渲染,界面展示效果,由于其易用性及便捷的维护应用日益广泛。而node作为一个服务器端语言,它是以javascript语言为基础的服务端程序语言,在实际的项目开发中,前端人员只要实现了环境的搭建,其实就可以仅仅从后台拿api接口进行数据调用,从而全部完成整个前端项目的展示。
前端由于近两年web前端技术发展革新速度飞快,一旦错过了,可能重新学的速度是非常慢的,只要尽早入手才能获得最好的学习效果。全栈网络专业从事郑州网站制作,我们也有专业的网站制作团队,愿意为每一个前端人员提供最新的前端知识分享。
co最简版实现,学习generator & co
看了co的源码 比较难懂 了解了其原理后实现了一个最简版本https://github.com/yucong/simple-co 希望对想学习的tx有帮助~ yeild后面只支持thunk,co本身也是一个thunk 核心代码:
- function co(generator) {
- return function(fn) {
- var gen = generator();
- function next(err, result) {
- if(err){
- return fn(err);
- }
- var step = gen.next(result);
- if (!step.done) {
- step.value(next);
- } else {
- fn(null, step.value);
- }
- }
- next();
- }
- }
用法:
- var co = require('./co');
- // wrap the function to thunk
- function readFile(filename) {
- return function(callback) {
- require('fs').readFile(filename, 'utf8', callback);
- };
- }
- co(function * () {
- var file1 = yield readFile('./file/a.txt');
- var file2 = yield readFile('./file/b.txt');
- console.log(file1);
- console.log(file2);
- return 'done';
- })(function(err, result) {
- console.log(result)
- });
会打印出: content in a.txt content in b.txt done
下面做个简单对比:
传统方式,sayhello
是一个异步函数,执行helloworld
会先输出"world"
再输出"hello"
。
- function sayhello() {
- return Promise.resolve('hello').then(function(hello) {
- console.log(hello);
- });
- }
- function helloworld() {
- sayhello();
- console.log('world');
- }
- helloworld();
输出
- > "world"
- > "hello"
co 的方式,会先输出"hello"
再输出"world"
。
- function co(gen) {
- var it = gen();
- var ret = it.next();
- ret.value.then(function(res) {
- it.next(res);
- });
- }
- function sayhello() {
- return Promise.resolve('hello').then(function(hello) {
- console.log(hello);
- });
- }
- co(function *helloworld() {
- yield sayhello();
- console.log('world');
- });
输出
- > "hello"
- > "world"
消除回调金字塔
假设sayhello
/sayworld
/saybye
是三个异步函数,用真正的 co 模块就可以这么写:
- var co = require('co');
- co(function *() {
- yield sayhello();
- yield sayworld();
- yield saybye();
- });
输出
- > "hello"
- > "world"
- > "bye"
搞定 koa 之generator 与 co
koa 是由 tj大神利用 generator 开发的 web 框架。要理解 koa,首先要先了解 generator 与 co。作为搞定 koa 的第一篇,我们便谈谈这个。文章首发在boke.io
generator介绍
function* Gene(){
yield 1;
yield 2;
}
var gene = Gene();
console.log(gene.next());//{ value: 1, done: false }
console.log(gene.next());//{ value: 2, done: false }
console.log(gene.next());//{ value: undefined, done: true }
console.log(gene.next());//Error: Generator has already finished 经@Ralph-Wang提醒从 v0.11.13 开始不抛错了,返回{ value: undefined, done: true }
从上面我们可以看到
generator 的定义和函数类似,只是在 function 后面多了一个*
调用generator 和调用函数一样,只是不像函数立即执行,而是会生成一个对象
generator 生成的对象存在一个 next 函数,调用 next 会返回 yield运算的结果对象,并停止。再次调用会在下一个 yield 处停止。
当所有的 yield 被执行完,调用 next 函数会返回{ value: undefined, done: true }。再次调用会报错
generator 与异步
看完 generator 的介绍,你心里回想这跟异步有毛关系?不着急听我接着说
串行请求两个网页的代码
var request = require('request');
var a = {};
var b = {};
request('http://www.google.com', function (error, response, body) {
if (!error && response.statusCode == 200) {
a.response = response;
a.body = body;
request('http://www.yahoo.com', function (error, response, body) {
if (!error && response.statusCode == 200) {
b.response = response;
b.body = body;
}
});
}
});
我们再看看最终我们是如何利用 generator请求网页的
co(function *(){
var a = yield request('http://google.com');
var b = yield request('http://yahoo.com');
console.log(a[0].statusCode);
console.log(b[0].statusCode);
})()
上面的代码可以看到,co 里面传入了一个 generator,里面用 yield 调用异步函数。从逻辑上看,里面的异步被变成了同步。
co 到底有什么魔法?可以把我们从异步中解救出来?
想想 generator 的特性,当我们执行第一个 next 的时候,会调用第一个 request,此时我们去调用 request 的逻辑,然后把 generator 的实例穿进去。当第一个 request 逻辑完成时,在调用这个 generator 的 next,这样就到了第二个 yield 的逻辑了。当然这需要一些逻辑的封装,也就是 co 了。
根据上面的分析,我们大概可以写出下面的代码
function co(Gene){
//先实例化一下
var gene = Gene();
//如果存在 next 函数
if(gene.next){
var fun = gene.next();//把异步函数返回过来,好继续封装
//fun 处理完,再调用 gene.next()
//...
}
}
从上面的代码可以看出
yield 后面的内容需要返回一个异步函数,这样我们才可进一步封装异步处理的逻辑。
fun 需要可以传入参数,这样才可以处理多个异步
需要一个递归调用,这样才可以持续调用 next,同时根据 next 返回对象中的done属性停止逻辑
需要考虑错误处理
今天就到这里,下一篇详细讲一下 co 的源码
co最简版实现,学习generator & co
看了co的源码 比较难懂 了解了其原理后实现了一个最简版本https://github.com/yucong/simple-co 希望对想学习的tx有帮助~ yeild后面只支持thunk,co本身也是一个thunk
核心代码:
function co(generator) {
return function(fn) {
var gen = generator();
function next(err, result) {
if(err){
return fn(err);
}
var step = gen.next(result);
if (!step.done) {
step.value(next);
} else {
fn(null, step.value);
}
}
next();
}
}
用法:
var co = require('./co');
// wrap the function to thunk
function readFile(filename) {
return function(callback) {
require('fs').readFile(filename, 'utf8', callback);
};
}
co(function * () {
var file1 = yield readFile('./file/a.txt');
var file2 = yield readFile('./file/b.txt');
console.log(file1);
console.log(file2);
return 'done';
})(function(err, result) {
console.log(result)
});
会打印出:
content in a.txt
content in b.txt
done
================================
generator_co: http://liuxinxiu.com/generator_co/
Node.js Cannot find module 'xxx' 问题解决(MAC)
使用npm install -g 'xxx' 之后仍然报
Cannot find module 'xxx' 错误,可以通过设置环境变量来解决;
export NODE_PATH=/usr/local/lib/node_modules/
echo $NODE_PATH
Error: Cannot find module 'ftp'
使用 Google V8 引擎开发可定制的应用程序
V8 引擎概览
NodeJS反向代理至后端数据接口
支持来自任何域名的Post请求,验证请求参数必须有: [name、gender] 否则直接JSON返回错误!
- var http=require('http');
- function server(){
- this.exec=function(route,req,res){
- var _self=this;
- /********** 获取客户端数组中的部分数据可向后多取 **********/
- this.arrv=function(o,n,p){
- var i,y,d,p;y=false;d='';
- for(i in o){
- if(o[i]==n&&p==undefined){i++;return o[i]};
- if(o[i]==n&&p!=undefined&&!isNaN(p)||y){
- var s;s=i;
- p=Number(p);
- if(p>0){
- p--;s++;d+=o[s];y=true;
- }
- else{
- return d;
- }
- }
- }
- };
- /********** 请求后端时可获取单个header头内地信息 **********/
- this.getReqHeaders=function(n){
- if(typeof(n)=='undefined'){
- console.log('getReqHeaders(n)变量没有定义!');
- }else{
- return _self.arrv(req.rawHeaders,String(n));
- }
- };
- /******** 获取客户端请求的header整体头部信息 ********/
- this.rawHeaders=function(state){
- var json={};
- if(!state){
- for(var i=0;i<req.rawHeaders.length;i++){
- var s,s=i;
- if(i%2==0){
- s++;json[req.rawHeaders[i]]=req.rawHeaders[s];
- }
- }
- }
- if(state){
- for(var i=0;i<req.rawHeaders.length;i++){
- json[i]=req.rawHeaders[i];
- }
- }
- var jsonStr=JSON.stringify(json);//结果:"{'1':'a','2':'b','3':'c'}"
- var jsonObj=JSON.parse(jsonStr); //结果:[object Object]
- return jsonObj;
- };
- //接收参数 ------ sreq.on("data",function(data){});接收html中ajax传递的参数
- req.on("data",function(data){
- /********* 打印提示||接受数据并反向代理到后端 *********/
- console.log("\n--->>\nReq.on('data')",req.method.toUpperCase()+" Use Proxy!");
- /********* 使用代理||这里Post请求体是回调data *********/
- send(route,req,res,data);
- });
- /********** 判断是GET请求类型||也可以代理给后端处理 **********/
- if(req.method.toUpperCase()=="GET"){
- var params=[];
- //params=url.parse(request.url,true).query;
- //params['fruit']=compute(params);
- res.writeHeader(200,{
- "Content-type":"text/html; charset=utf-8"
- });
- res.write('<h1>It is forbidden for the URL request!</h1>');
- res.write('<hr><address>NodeJs/'+process.version);
- res.write(' at '+req.headers.host.split(':')[0]);
- res.write(' Port '+req.headers.host.split(':')[1]+'</address>');
- res.end();
- }
- /********* 如有req.on("data",function(data){});就跳过了以下方法 ******/
- /********* 判断是POST请求类型||提交不走代理此方法是本机处理回调 **********/
- else if(req.method.toUpperCase()=='POSTo'){
- var postData="";
- /********** 读取Post提交的数据 **********/
- req.addListener("data",function(data){
- postData+=data;
- });
- /********** 数据读取完毕就会执行的监听 *********/
- req.addListener("end",function(){
- /********* 定义Post请求主体 *********/
- var query=require('querystring').parse(postData);
- /************** 判断如果有POST过来数据 *************/
- if(query.name&&query.gender){
- console.log('Start a request...');
- var origin=_self.arrv(req.rawHeaders,'Origin');
- console.log("origin:"+typeof req.rawHeaders+'---')
- /********** 代理转发至php,跨域全放开让后端去匹配验证 **********/
- //res.setHeader('Access-Control-Allow-Origin','*');
- //res.setHeader('Access-Control-Allow-Headers','X-Requested-With');
- //res.setHeader('Access-Control-Allow-Methods','GET,POST,PUT,DELETE,OPTIONS');
- //send(route,req,res,query);
- }
- /****** 判断结束 ******/
- });
- }
- /******** 请求后端接口 ********/
- function send(route,req,res,data){
- /***************************************
- var data={
- name:'liuxinxiu',
- gender:"male",
- time:new Date().getTime()
- };
- ****************************************/
- //data=require('querystring').stringify(data);
- var rawHeaders=_self.rawHeaders();
- /********** 判断一个对象是哪中类型的对象 **********/
- function isArray(obj){
- return Object.prototype.toString.call(obj)==='[object Array]';
- };
- /********* 打印Request Headers **********/
- console.log("\n--->>\nRequest Headers:",req.rawHeaders);
- /***** 向后端发送请求基本的设置 *****/
- var options={
- port: 80,
- host:"code.liuxinxiu.com",
- path:'/php/Post/CORS_PHP.php',
- method: 'POST',
- headers:{
- 'Content-Type':_self.getReqHeaders('Content-Type'),
- 'Content-Length':data.length,
- 'Origin':_self.getReqHeaders('Origin'),
- 'User-Agent':_self.getReqHeaders('User-Agent')
- }
- };
- /***** 如果header整体替换就会乱码 *****/
- //options.headers=_self.rawHeaders();
- var request=http.request(options,function(result){
- console.log("\n--->>\nstatusCode:",result.statusCode);
- console.log("\n--->>\nResponse Headers:",result.headers);
- if(result){
- var content_type,origin,x_powered_by,server;
- //content_type=origin=x_powered_by=server=undefined;
- content_type=result.headers['content-type'];
- origin=result.headers['access-control-allow-origin'];
- x_powered_by=result.headers['x-powered-by'];
- server=result.headers['server'];
- /********** 判断分别加入包含服务器错误页 **********/
- if(origin!=undefined&&result.statusCode==200){
- res.setHeader('Access-Control-Allow-Origin',origin);
- }
- if(content_type!=undefined){
- res.setHeader('Content-Type',content_type);
- }
- if(x_powered_by!=undefined){
- res.setHeader('X-Powered-By',x_powered_by);
- }
- if(server!=undefined){
- res.setHeader('Server',server);
- }
- }
- /********** 有异常的请求需要问题定位 **********/
- if(result.statusCode<200||result.statusCode>206){
- }
- /********** 接受数据数据监听 **********/
- var _data='';
- result.on('data',function(chunk){
- _data+=chunk;
- });
- /********** 结束接受数据监听 *********/
- result.on('end',function(){
- console.log("\n--->>\nresult:",_data);
- res.write(_data);
- res.end();
- });
- /******** request逻辑完成 ********/
- });
- request.on('error',function(e) {
- console.log('problem with request: ' + e.message);
- });
- //request.write(data);
- request.write(data+"\n");
- request.end();
- }
- /****** 内部结束 ******/
- }
- }
- module.exports=new server();
NodeJS数据接口(Post请求直接代理至后端PHP): http://liuxinxiu.com:3000/CORS_Node_Proxy/
PHP数据接口(验证跨域提交白名单外返回错误): http://code.liuxinxiu.com/php/Post/CORS_PHP.php
CORS||跨域资源共享||NodeJs版本实现
使用NodeJs实现CORS 跨域资源共享,可传参origin通过限制,代码如下:
- var http=require('http');
- var origin=require('./origin'); //调用白名单列表
- function CORS_Node(){
- this.exec=function(route,req,res){
- var _self=this;
- /************** 获取客户端origin的域名 **************/
- origin.req=req; //白名单设置置请求头
- origin.yes=origin.listV(); //是否在名单|true
- origin.name=origin.getName(); //客户端ORIGIN
- /******** 先纠正参数,参数正确后匹配白名单 ********/
- /********** 判断是GET请求类型 **********/
- if(req.method.toUpperCase()=="GET"){
- var params=[];
- //params=url.parse(request.url,true).query;
- //params['fruit']=compute(params);
- res.writeHeader(200,{
- "Content-type":"text/html; charset=utf-8"
- });
- res.write('<h1>It is forbidden for the URL request!</h1>');
- res.write('<hr><address>NodeJs/'+process.version);
- res.write(' at '+req.headers.host.split(':')[0]);
- res.write(' Port '+req.headers.host.split(':')[1]+'</address>');
- res.end();
- }
- /********* 判断是POST请求类型 **********/
- else if(req.method.toUpperCase()=='POST'){
- var postData="";
- /********** 读取Post提交的数据 **********/
- req.addListener("data",function(data){
- postData+=data;
- });
- /********** 数据读取完毕就会执行的监听 *********/
- req.addListener("end",function(){
- /********* 定义Post请求主体 *********/
- var query=require('querystring').parse(postData);
- /********** 给客户端返回数据自造JSON **********/
- function getJson(status){
- if(isNaN(status))status=-1;
- else{status=Number(status)}
- var _drr='{'
- +'"status":"1",'
- +'"name":"'+query.name+'",'
- +'"gender":"'+query.gender+'"}';
- var _arr='{'
- +'"status":1,'
- +'"url":"http://www.liuxinxiu.com/",'
- +'"dataList":'
- +'{'
- +'"siteId":101,'
- +'"title":"我的博客||Node Server",'
- +'"images":"http://www.liuxinxiu.com/upload/2016/08/10/moren.gif",'
- +'"indexNum":"10",'
- +'"pageNum":"100000",'
- +'"tagNum":"22",'
- +'"linkType":"linkTaobao",'
- +'"publishTime":"23:15:30"'
- +'}'
- +'}';
- this._dr=JSON.parse(_drr);this._ar=JSON.parse(_arr);
- this._dt=this._dr;this._dt.getUser=this._ar;
- }
- var errStr={"status":-1,"info":"Request Error"};
- /********** 先初步设置头信息,跨域全放开稍后再进行匹配验证 **********/
- var content_type,content_length,
- content_type='application/json; charset=utf-8';
- content_length=Buffer.byteLength(res,'utf8');
- res.setHeader('Access-Control-Allow-Origin','*');
- res.setHeader('Access-Control-Allow-Headers','X-Requested-With');
- res.setHeader('Access-Control-Allow-Methods','GET,POST,PUT,DELETE,OPTIONS');
- res.setHeader('Content-Type',content_type);
- res.setHeader('Server','NodeJs/'+process.version);
- /************** 判断如果有POST过来规范的数据 *************/
- if(query.name&&query.gender){
- //调用数据
- getJson(1);
- /******** 匹配客户端域名是否在数组列表中 ******/
- //if(_self.in_array(origin,allow_origin)){
- if(origin.yes){
- res.setHeader('Access-Control-Allow-Origin',origin.name);
- res.end(JSON.stringify(_dt));
- }
- else{
- /******** 如有设置就取设置URL返回头信息 ********/
- if(query.origin){
- res.setHeader('Access-Control-Allow-Origin',query.origin);
- res.end(JSON.stringify(_dt));
- }
- /******** 没设置URL就返回无权限错误信息 ********/
- else{
- errStr.info="You don't have permission to submit!";
- res.setHeader('Access-Control-Allow-Origin',origin.name);
- res.end(JSON.stringify(errStr));
- }
- }
- }
- /********* 没有所匹配的POST提交数据||都要设头返回信息 ********/
- else{
- /******** 其他POST参数的提交 ********/
- if(query){
- res.writeHeader(res.statusCode,{
- "Access-Control-Allow-Origin":origin.name,
- "Access-Control-Allow-Headers":"X-Requested-With",
- "Access-Control-Allow-Methods":"GET,POST,PUT,DELETE,OPTIONS",
- "Content-type":"application/json; charset=utf-8"
- });
- var err={status:-1,info:"Syntax error in parameters or arguments."};
- res.end(JSON.stringify(err));
- }
- else{
- res.writeHeader(res.statusCode,{
- "Content-type": "text/html; charset=utf-8"
- });
- res.end('It is forbidden for the URL request!');
- }
- }
- /****** 判断结束 ******/
- });
- }
- /****** 内部结束 ******/
- }
- }
- module.exports=new CORS_Node();
NodeJs数据提交接口地址 (不允许使用GET访问) :http://liuxinxiu.com:3000/CORS_Node/
注意:NodeJs Server 是本站的测试环境,有时候因需要会临时关闭,该地址仅供测试,如您有需要请自建环境~
配合HTML代码如下:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8"/>
- <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
- <meta name="format-detection"content="telephone=no">
- <meta name="apple-mobile-web-app-capable" content="yes" />
- <meta name="apple-mobile-web-app-status-bar-style" content="black" />
- <style>body,html {background:#fff;font-family: "Lucida Grande",Calibri,Arial;font-size:12pt;color: #333;background: #f8f8f8;text-align:center;}*{margin:0;padding:0;}h1{line-height:1.6em;font-size:24px;text-indent:.5em;padding-top:.6em}i{line-height:2em;font-size:18px;color:#999;}.line{height:10px;border-bottom:1px solid #ccc;font-size:0;overflow:hidden;}</style>
- <title>跨域测试</title>
- </head>
- <body>
- <h1 id="show"></h1>
- <input type="button" value="Click me" onclick="msg()" />
- </body>
- <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
- <script type='text/javascript'>
- /********** 获取URL参数 **********/
- function getQueryString(name){
- var reg=new RegExp("(^|&)"+name+"=([^&]*)(&|$)","i");
- var r=window.location.search.substr(1).match(reg);
- if (r!=null) return unescape(r[2]); return null;
- }
- var _n=getQueryString('n');
- var _url=getQueryString('url');
- var _name=getQueryString('name');
- var _gender=getQueryString('gender');
- var _origin=getQueryString('origin');
- var _error=getQueryString('error');
- console.log('origin:'+_origin+' —— name:'+_name+' —— gender:'+_gender);
- window.onload=function(){
- if(_n=='php'){
- location.href='http://'
- +location.host
- +location.pathname
- +'?origin=http://'+location.host;
- }else if(_n=='node'){
- location.href='http://'
- +location.host
- +location.pathname
- +'?origin=http://'+location.host+'&'
- +'url=http://liuxinxiu.com:3000/CORS_Node/'
- }else if(_n=='proxy'){
- location.href='http://'
- +location.host
- +location.pathname
- +'?origin=http://'+location.host+'&'
- +'url=http://liuxinxiu.com:3000/CORS_Node_Proxy/'
- }else if(_n=='test'){
- location.href='http://test1.liuxinxiu.com/php/Interface/html/server.html'
- +'?origin=http://test1.liuxinxiu.com&'
- +'url=http://liuxinxiu.com:3000/CORS_Node_Proxy/&'
- +'error=1'
- }
- }
- /********** 发起Ajax请求 **********/
- function msg(){
- /******* 动态切换提交数据 *******/
- if(_origin&&!_error){
- if(_name&&_gender){
- var data={name:_name,gender:_gender,origin:_origin};
- }
- else{
- var data={name:"xiaoming",gender:"male",origin:_origin};
- }
- }
- else if(_error==null){
- var data={name:"xiaoming",gender:"male"};
- }
- else if(_error){
- var data={xxx:111};
- }
- /******* 动态设置提交URL *******/
- if(_url){
- var urlPath=_url;
- }
- else{
- var urlPath='http://code.liuxinxiu.com/php/Post/CORS_PHP.php';
- }
- $.ajax({
- type:'post',
- url:urlPath,
- data:data,
- cache:false,
- dataType:'json',
- success:function(data){
- if(data.name){
- document.getElementById("show").innerHTML=data.name+' '+data.gender;
- }
- else if(data.status!=1){
- document.getElementById("show").innerHTML=data.info;
- }
- },
- error:function(){
- console.log("请求错误//")
- }
- });
- };
- /***********************************************************************************************
- $.post("http://www.server.com/server.php",{name:"fdipzone",gender:"male"}).done(function(data){
- document.getElementById("show").innerHTML=data.name+' '+data.gender;
- });
- **********************************************************************************************/
- </script>
- </html>
HTML访问地址 (测试跨域) ==> http://test1.liuxinxiu.com/php/Interface/html/server.html?n=node
HTML访问地址 (非法参数) ==> http://test1.liuxinxiu.com/php/Interface/html/server.html?error=node
注意:本站的 NodeJs Server 是学习测试环境,有临时关闭的可能,建议在本地环境测试~
NodeJs JSONP数据接口定义
- var http = require('http');
- var urllib = require('url');
- var port = 10011;
- var data = {'name': 'jifeng', 'company': 'taobao'};
- http.createServer(function(req, res){
- var params = urllib.parse(req.url, true);
- console.log(params);
- if (params.query && params.query.callback) {
- //console.log(params.query.callback);
- var str = params.query.callback + '(' + JSON.stringify(data) + ')';//jsonp
- res.end(str);
- } else {
- res.end(JSON.stringify(data));//普通的json
- }
- }).listen(port, function(){
- console.log('server is listening on port ' + port);
- })
自建Node路由Jsonp接口访问地址:http://liuxinxiu.com:3000/jsonp?Jsoncallback=2016&&name=liuxinxiu
- function jsonp(){
- this.exec=function(route,req,res){
- var data1={key:'value',hello:'world',name:'刘新修'};
- var data2={'name':'wangjiang','company':'taobao'};
- console.log(req+'---'+route)
- res.statusCode=200;
- //res.setHeader('content-type','application/json;charset=utf-8');
- //res.setHeader('Content-Type','text/html');
- //req.write(data);
- //req.end();
- var params=url.parse(req.url,true);
- console.log(params);
- if(params.query&¶ms.query.Jsoncallback){
- console.log(params.query.Jsoncallback);
- var str=params.query.Jsoncallback+'('+JSON.stringify(data1)+')';//jsonp
- res.end(str);
- }
- else{
- res.writeHead(200,{'Content-Type':'application/json'});
- res.end(JSON.stringify(data1)); //普通的json
- }
- }
- }
- module.exports=new jsonp();
自建Node路由Jsonp接口访问地址:http://liuxinxiu.com:3000/Jsoncallback?Jsoncallback=1&name=Jack
- function jsoncallback(){
- this.exec=function(route,req,res){
- /******** 处理请求判断用作JSONP ********/
- var params=url.parse(req.url,true);
- /********** 造数据要Obj不要String **********/
- var str2={dataList:[{name:"Jack",age:28,sex:1},{name:'Tony',age:30,sex:0}]};
- /********** 映射数据源无为undefined **********/
- var output=2016+'('+JSON.stringify(str2)+')';
- var result=params.query.Jsoncallback+'('+JSON.stringify(str2)+')';
- /************* 定义头部信息及编码规范 *******************/
- res.writeHead(200,{'content-Type':'application/json;charset=utf-8'});
- /************* 判断出来相应返回的结果 ********************/
- if(params.query&¶ms.query.Jsoncallback){
- res.write(result);
- res.end();
- }
- else{
- res.write(output);
- res.end();
- }
- }
- };
- module.exports=new jsoncallback();