AJAX笔记

原生AJAX


AJAX 简介

  • 全称为Asynchronous JavaScript And XML,即异步的 JS 和 XML
  • 通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无需刷新即可获取数据
  • AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式

AJAX 的特点

  • 优点:① 可以无需刷新页面而与服务器端进行通信;② 允许根据用户事件来更新部分页面内容
  • 缺点:① 没有浏览历史,不能回退;② 存在跨域问题(同源);③ SEO(搜索引擎优化)不友好

HTTP 协议

超文本传输协议,协议详细规定了浏览器和万维网服务器之间相互通信的规则

使用


Express的安装和使用

// 安装 npm install express
// 引入express
const express = require("express");
// 创建应用对象
const app = express();
// 创建路由规则:request请求报文 response响应报文
app.get("/server", function (request, response) {
  // 设置响应头 设置允许跨域
  response.setHeader("Access-Control-Allow-Origin", "*");
  // 设置响应体
  response.send("hello ajax get");
});
// 监听端口启动服务
app.listen(8000, function () {
  console.log("服务已经启动,8000端口监听中...");
});

使用 Ajax 发送 GET 请求

<style>
    #result {
        width: 200px;
        height: 100px;
        border: 1px solid #000;
    }
</style>
<button>点击发送请求</button>
<div id="result"></div>
<script>
    $('button').on("click", function () {
        // 创建对象
        const xhr = new XMLHttpRequest();
        // 初始化 设置请求的方法和URL ?后是设置的参数
        xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');
        // 发送
        xhr.send();
        // 事件绑定 处理服务端返回的结果 
        /* 
            readyState 是xhr对象中的属性
                0 未初始化 
                1 open方法调用完毕
                2 send方法调用完毕
                3 服务端返回了部分结果
                4 服务端返回了所有结果
        */
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                // 判断响应状态码
                if (xhr.status >= 200 && xhr.status < 300) {
                    // 处理结果 行 头 体
                    console.log(xhr.status, xhr.statusText); // 状态码 状态字符串
                    console.log(xhr.getAllResponseHeaders()); // 所有响应头
                    console.log(xhr.response); // 响应体
                    // 将响应内容写入div
                    $('#result').html(xhr.response);
                }
            }
        };
    })
</script>

使用 Ajax 发送 POST 请求

// all() 可以接收所有类型的请求
app.post("/server", function (request, response) {
  // 设置响应头 设置允许跨域
  response.setHeader("Access-Control-Allow-Origin", "*");
  // response.setHeader("Access-Control-Allow-Headers", "*"); // 可以接收自定义的请求头信息
  // 设置响应体
  response.send("hello ajax post");
});
<style>
    #result {
        width: 200px;
        height: 100px;
        border: 1px solid #000;
    }
</style>
<div id="result"></div>
<script>
    $('#result').on("mouseenter", function () {
        // 创建对象
        const xhr = new XMLHttpRequest();
        // 初始化 设置请求的方法和URL 
        xhr.open('POST', 'http://127.0.0.1:8000/server');
        // 设置请求头 请求体内容的类型
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.setRequestHeader('name', 'dudu'); // 添加自定义头部信息会报错,需要在服务器进行配置
        // 发送 请求体中可以写任何内容,只要服务端可以解析
        xhr.send('a=100&b=200&c=300');
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                // 判断响应状态码
                if (xhr.status >= 200 && xhr.status < 300) {
                    // 处理结果 行 头 体
                    console.log(xhr.status, xhr.statusText); // 状态码 状态字符串
                    console.log(xhr.getAllResponseHeaders()); // 所有响应头
                    console.log(xhr.response); // 响应体
                    // 将响应内容写入div
                    $('#result').html(xhr.response);
                }
            }
        };
    })
</script>

服务端响应 json 数据

app.all("/json-server", function (request, response) {
  // 设置响应头 设置允许跨域
  response.setHeader("Access-Control-Allow-Origin", "*");
  const data = {
    name: "dudu",
    age: 22,
  };
  // 设置响应体
  response.send(JSON.stringify(data));
});

手动转换响应体数据

const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8000/server');
xhr.send('a=100&b=200&c=300');
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
        // 判断响应状态码
        if (xhr.status >= 200 && xhr.status < 300) {
            // 处理结果 行 头 体
            console.log(xhr.status, xhr.statusText); // 状态码 状态字符串
            console.log(xhr.getAllResponseHeaders()); // 所有响应头
            console.log(JSON.parse(xhr.response)); // 响应体
            // 将响应内容写入div
            $('#result').html(JSON.parse(xhr.response).name);
        }
    }
};

自动转换响应体数据

const xhr = new XMLHttpRequest();
// 设置响应体数据的类型 自动转换
xhr.responseType = 'json';
xhr.open('GET', 'http://127.0.0.1:8000/server');
xhr.send('a=100&b=200&c=300');
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
        // 判断响应状态码
        if (xhr.status >= 200 && xhr.status < 300) {
            // 处理结果 行 头 体
            console.log(xhr.status, xhr.statusText); // 状态码 状态字符串
            console.log(xhr.getAllResponseHeaders()); // 所有响应头
            console.log(xhr.response); // 响应体
            // 将响应内容写入div
            $('#result').html(xhr.response.name);
        }
    }
};

nodemon 工具介绍
作用:可以自动重启node应用
安装:npm install -g nodemon
使用:使用nodemon server.js 来启动服务


IE缓存问题解决

  • IE会对Ajax请求返回的响应体进行缓存,如果两次进行URL相同的请求,IE不会进行新的请求会返回缓存中的内容
  • 解决:使用xhr.open('GET', 'http://127.0.0.1:8000/server?t=' + Date.now());进行访问,每次都是不同的URL

请求超时与网络异常

app.get("/server", function (request, response) {
  response.setHeader("Access-Control-Allow-Origin", "*");
  setTimeout(function () {
    response.send("5s延时响应");
  }, 5 * 1000);
});
const xhr = new XMLHttpRequest();
// 超时设置 如果2s内没有返回结果,请求就取消
xhr.timeout = 2 * 1000;
// 超时回调
xhr.ontimeout = function () {
    alert('网络异常,请稍后重试');
};
// 网络异常
xhr.onerror = function () {
	alert('你的网络似乎出了一些问题!');
}
xhr.open('GET', 'http://127.0.0.1:8000/server');
xhr.send();
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
        if (xhr.status >= 200 && xhr.status < 300) {
            $('#result').html(xhr.response);
        }
    }
};

手动取消请求

<button>点击发送</button>
<button>点击取消</button>
<script>
    let xhr = null;
    $('button').eq(0).on("click", function () {
    	xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://127.0.0.1:8000/server');
        xhr.send();
    });
    $('button').eq(1).on("click", function () {
    	xhr = new XMLHttpRequest();
    	// 手动取消请求
        xhr.abort();
    });
</script>

重复发送请求的处理

let xhr = null;
// 标识是否正在发送Ajax请求
let isSending = false;
$('button').eq(0).on("click", function () {
    if (isSending) {
        xhr.abort();
    }
    xhr = new XMLHttpRequest();
    isSending = true;
    xhr.open('GET', 'http://127.0.0.1:8000/server');
    xhr.send();
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            isSending = false;
        }
    };
});

jQuery 中的 Ajax

$.get('http://127.0.0.1:8000/jq-server', { a: 100, b: 200 }, function (data) {
    console.log(data);
}, 'json');
$.post('http://127.0.0.1:8000/jq-server', { a: 100, b: 200 }, function (data) {
	console.log(data);
});
$.ajax({
    url: 'http://127.0.0.1:8000/jq-server',
    data: { a: 100, b: 200 },
    type: 'GET',
    dataType: 'json',
    success: function (data) {
        console.log(data);
    },
    timeout: 2 * 1000,
    error: function () {
        console.log('出错啦');
    },
    headers: {
        c: 300,
        d: 400
    }
});

Axios 发送 Ajax 请求

// 配置 baseURL
axios.defaults.baseURL = 'http://127.0.0.1:8000';
$('button').eq(0).on("click", function () {
    axios.get('/server', {
        params: {
            a: 100,
            b: 200
        },
        headers: {
            name: 'dudu',
            age: 20
        }
    }).then(value => {
        // 包括详细响应信息的对象
        console.log(value);
    });
});
$('button').eq(1).on("click", function () {
    axios.post('/server',
        // 请求体
        {
            name: 'dudu',
            age: 20
        },
        {
            params: {
                a: 100,
                b: 200
            },
            headers: {
                name: 'dudu',
                age: 20
            },
        }
    );
});
$('button').eq(2).on("click", function () {
    axios({
        method: 'post',
        url: '/server',
        params: {
            a: 100, b: 200
        },
        headers: {},
        data: {}
    });
});

fetch 方法发送 Ajax 请求

$("button").eq(0).on("click", function () {
  fetch("http://127.0.0.1:8000/server?vip=10", {
    method: "post",
    headers: {
      name: "dudu",
    },
    body: "username=admin&password=admin",
  }).then((response) => {
    // return response.text();
    return response.json();
  }).then((response) => {
    console.log(response);
  });
});

跨域

  • 同源策略:协议、域名、端口号必须完全相同。违背同源策略就是跨域
  • Ajax默认遵循同源策略
解决方式一:JSONP
  • JSONP 是一个非官方的跨域解决方案,只支持 get 请求。
  • 在网页中有一些标签天生具有跨域能力,比如:img link iframe script,JSONP就是利用 script 标签的跨域能力来发送请求的
用户名:<input type="text" id="username">
<p></p>
<script>
	$("#username").on("blur", function () {
        var name = this.value;
        // 发送请求,检测用户名是否存在
        var url = "http://127.0.0.1:8000/server";
        var $request = $('<script src="' + url + '"><//script>');
        $('body').append($request);
    });
    function handle(data) {
    	$("#username").css("border", "solid 1px red");
    	$('p').html(data.msg);
    }
</script>
app.all("/server", function (request, response) {
  response.setHeader("Access-Control-Allow-Origin", "*");
  const data = {
    exist: 1,
    msg: "用户名已经存在",
  };
  // 设置响应体
  response.end("handle(" + JSON.stringify(data) + ")");
});

jQuery 实现

<button>点击发送jsonp请求</button>
<p></p>
<script>
    $("button").on("click", function () {
        var url = "http://127.0.0.1:8000/server?callback=?";
        $.getJSON(url, function (data) {
            $('p').html("姓名:" + data.name + "<br/>年龄:" + data.age);
        });
    });
</script>
app.all("/server", function (request, response) {
  response.setHeader("Access-Control-Allow-Origin", "*");
  const data = {
    name: "dudu",
    age: 22,
  };
  let cb = request.query.callback;
  // 设置响应体
  response.end(cb + "(" + JSON.stringify(data) + ")");
});
解决方式二:CORS(跨域资源共享)
  • 官方的跨域解决方案
  • 不需要在客户端坐任何特殊的操作,完全在服务器中进行处理
  • 支持get和post请求
  • 通过设置一组响应头来完成配置,例如: response.setHeader("Access-Control-Allow-Origin", "*");,其他的请求头可以参考 https://developer.mozilla.org/zh-CN/docs/Glossary/CORS
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值