挚爱原生之ajax——拓展跨域promise\fetch\jsonp\ascyn&await(一)

前言

关于ajax的原生实现是一个老生常谈的话题,之因此再提出,一是熟悉原生写法,二也是最重要的,跨域,众所周知,ajax不支持跨域,这必定言为广大程序猿所熟知,但不少新手都只到这一层就放弃了继续深刻的契机,再者随着时代的发展,一系列支持跨域的websocket、ajax2.0等新特性出现,联系以前的jsonp,小菜决定来次小小的总结,若有纰漏望看官不吝赐教,html

========================================================= 写着写着发现太长了,就分段了,本文实现了原生ajax,解析SOP同源策略,解决原生AJAX跨域========================================================== 前端

本文主要实现node

  • 原生实现ajax
  • 原生ajax跨域解决
  • 跨域三剑客:websocket、ajax2.0、jsonp

正文

原生实现ajax

  • 目录结构
  1. 用node搭建一个简单的服务器 若不了解node能够点击下面连接,我在其中有详细步骤 juejin.im/post/5cadc2…
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)
复制代码
  1. 准备数据 由于只是简单测试ajax,就不上数据库了,建一个json文件,存些数据,包结构如上,数据以下
{
    "name":"小菜",
    "dream":"家人身體健康"
}
复制代码
  • 此时浏览器直接访问,响应以下

  1. 前端实现原生XMLHttpRequest发起请求
<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

这是咱们后面能解决的问题,如今先放在这,咱们先简单的经过服务器打开html使之同源 改进版的服务端代码,其实就是加了个html访问接口

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

就会惊讶(常理)的发现,成啦,哈哈 这个时候咱们也就实现原生的异步请求啦,可是,这不是咱们的目的,咱们如今回过头来,找到刚刚害咱们一顿折腾的跨域报错,同源策略数据库

同源策源SOP

同源策略(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)
复制代码
  • 重点:res.writeHeader(200,{"Content-Type":"text/html;charset=utf-8",'access-control-allow-origin':'*'});
    这个时候咱们也就实现了原生跨域了,但这样有点安全问题,我们能够配置路由经过origin进行筛选,在这就不细说了
相关文章
相关标签/搜索