关于ajax的原生实现是一个老生常谈的话题,之因此再提出,一是熟悉原生写法,二也是最重要的,跨域,众所周知,ajax不支持跨域,这必定言为广大程序猿所熟知,但不少新手都只到这一层就放弃了继续深刻的契机,再者随着时代的发展,一系列支持跨域的websocket、ajax2.0等新特性出现,联系以前的jsonp,小菜决定来次小小的总结,若有纰漏望看官不吝赐教,html
========================================================= 写着写着发现太长了,就分段了,本文实现了原生ajax,解析SOP同源策略,解决原生AJAX跨域========================================================== 前端
本文主要实现node
const http = require('http');
const fs = require('fs');
const url = require('url');
http.createServer((req,res)=>{
let {pathname,query} = url.parse(req.url,true);
// console.log(pathname,query)
//将全部要响应的数据放在data文件夹下
pathname = `/data${pathname}`;
//解析路径进行判断,若请求正确才返回
if(pathname === '/data/data.json'){
fs.readFile('./data/data.json',(error,buffer)=>{
//避免返回中文乱码
res.writeHeader(200,{"Content-Type":"text/html;charset=utf-8"});
res.write(buffer);
res.end();
})
}else{
res.writeHeader(404);
res.write('NOT Found');
res.end();
}
}).listen(8080)
复制代码
{
"name":"小菜",
"dream":"家人身體健康"
}
复制代码
<script>
const xhr = new XMLHttpRequest();
xhr.open('get','./data.json',true);
xhr.send();
xhr.onreadystatechange = function(){
// 链接状态 枚举类型 0 初始化 1 已链接 2 已发送 3 接收当响应头 4 接收到响应体(即完成)
if(xhr.readyState == 4){
// 正则 ,意为首位为2的三位数 状态码304 也表示请求成功,只不过是告诉浏览器要去缓存中拿数据
if(/^2\d\d$/.test(xhr.status) || xhr.status ==304 ){
//响应数据
alert(xhr.responseText)
}
}
}
</script>
复制代码
这时候,若是直接打开html,就会报以下错误,缘由是跨域了(跨域:协议,域名,端口三者有一不一样即为跨域)web
const http = require('http');
const fs = require('fs');
const url = require('url');
http.createServer((req,res)=>{
let {pathname,query} = url.parse(req.url,true);
// console.log(pathname,query)
//将全部要响应的数据放在data文件夹下
pathname = `/data${pathname}`;
console.log(pathname)
//解析路径进行判断,若请求正确才返回
if(pathname === '/data/data.json'){
fs.readFile('./data/data.json',(error,buffer)=>{
//避免返回中文乱码
res.writeHeader(200,{"Content-Type":"text/html;charset=utf-8"});
res.write(buffer);
res.end();
})
}else if(pathname === '/data/index.html'){
fs.readFile('./data/index.html',(error,buffer)=>{
res.write(buffer);
res.end();
})
}
else{
res.writeHeader(404);
res.write('NOT Found');
res.end();
}
}).listen(8080)
复制代码
这个时候咱们再访问localhost:8080/index.htmlajax
就会惊讶(常理)的发现,成啦,哈哈 这个时候咱们也就实现原生的异步请求啦,可是,这不是咱们的目的,咱们如今回过头来,找到刚刚害咱们一顿折腾的跨域报错,同源策略数据库
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,若是缺乏了同源策略,则浏览器的正常功能可能都会受到影响。能够说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。 ------------------------------我是分割线--------------------------------------------------- 以上解释来自百度百科,非小菜所言json
其实就一句话:跨域请求响应回来的数据,浏览器会默认丢掉,并顺手给你报个大大的红错,hhh跨域
其实这正是一种安全访问思想的体现,也正是咱们废弃jsonp的缘由(稍后解释);但这样咱们若是有需求咋办?总不可能和客户解释SOP吧,那会被打死;这难不倒咱们万能的程序猿,没有女朋友有右手,换个角度曲线救国;其实从上面的定义咱们能够获得一个信息:浏览器
const http = require('http');
const fs = require('fs');
const url = require('url');
http.createServer((req,res)=>{
let {pathname,query} = url.parse(req.url,true);
// console.log(pathname,query)
//将全部要响应的数据放在data文件夹下
pathname = `/data${pathname}`;
console.log(pathname)
//解析路径进行判断,若请求正确才返回
if(pathname === '/data/data.json'){
fs.readFile('./data/data.json',(error,buffer)=>{
//避免返回中文乱码
// res.setHeader('access-control-allow-origin', '*');
//重点
res.writeHeader(200,{"Content-Type":"text/html;charset=utf-8",'access-control-allow-origin':'*'});
res.write(buffer);
res.end();
})
}else if(pathname === '/data/index.html'){
// res.setHeader();
res.writeHeader(200,{"Content-Type":"text/html;charset=utf-8"});
fs.readFile('./data/index.html',(error,buffer)=>{
res.write(buffer);
res.end();
})
}
else{
res.writeHeader(404);
res.write('NOT Found');
res.end();
}
}).listen(8080)
复制代码