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

前言

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

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

本文主要实现

  • 原生实现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,就会报如下错误,原因是跨域了(跨域:协议,域名,端口三者有一不同即为跨域)

这是我们后面能解决的问题,现在先放在这,我们先简单的通过服务器打开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.html

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

同源策源SOP

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。 ------------------------------我是分割线--------------------------------------------------- 以上解释来自百度百科,非小菜所言

其实就一句话:跨域请求响应回来的数据,浏览器会默认丢掉,并顺手给你报个大大的红错,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进行筛选,在这就不细说了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值