【初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域】

news2024/11/17 23:31:56

初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域

  • 1 初识前后端交互
  • 2 原生Ajax
    • 2.1 Ajax基础
    • 2.2 Ajax案例
    • 2.3 ajax请求方式
  • 3 Fetch
    • 3.1 fetch基础
    • 3.2 fetch案例
  • 4 axios
    • 4.1 axios基础
    • 4.2 axios使用
      • 4.2.1 axios拦截器
      • 4.2.2 axios中断器
  • 5 同源策略
  • 6 解决跨域
    • 6.1 jsonp
    • 6.2 其他技术手段

1 初识前后端交互

  • 传统网站的问题:
    1> 为了获取数据,需要重新加载,浪费资源,增加等待时间,性能不好。
    2> 验证表单过程中,一项内容不合格,页面需要重新加载,体验不好。
  • 解决问题:
    1> ajax 全名 async javascript and XML
    2> 是前后台交互的能力
    3> 也就是我们客户端给服务端发送消息的工具,以及接受响应的工具
    4> 是一个默认异步执行机制的功能
  • AJAX的优势:
    1> 不需要插件的支持,原生 js 就可以使用
    2> 用户体验好(不需要刷新页面就可以更新数据)
    3> 减轻服务端和带宽的负担
    4> 缺点: 搜索引擎的支持度不够,因为数据都不在页面上,搜索引擎搜索不到

2 原生Ajax

2.1 Ajax基础

  • 在 js 中有内置的构造函数来创建 ajax 对象;
const xhr = new XMLHttpRequest()
// 上面就是有了一个 ajax 对象
// 我们就可以使用这个 `xhr` 对象来发送 ajax 请求了
  • 配置链接信息;
xhr.open("get","1.json ",true)
// xhr.open('请求方式', '请求地址', 是否异步)
// xhr 对象中的 open 方法是来配置请求信息的
// 第一个参数是本次请求的请求方式 get / post / put / ...
// 第二个参数是本次请求的 url
// 第三个参数是本次请求是否异步,默认 true 表示异步,false 表示同步
  • 创建 ajax 对象以后,我们就使用 ajax 对象的方法去发送请求和接受响应。
xhr.send()
// 使用 xhr 对象中的 send 方法来发送请求
// 上面代码是把配置好信息的 ajax 对象发送到服务端
一、一个基本的ajax请求:
	一个最基本的 ajax 请求就是上面三步
	但是光有上面的三个步骤,我们确实能把请求发送的到服务端
	如果服务端正常的话,响应也能回到客户端,但是我们拿不到响应
	如果想拿到响应,我们有两个前提条件:
		1. 本次 HTTP 请求是成功的,也就是我们之前说的 http 状态码为 200 ~ 299
		2. ajax 对象也有自己的状态码,用来表示本次 ajax 请求中各个阶段
二、ajax 状态码:
	ajax 状态码 —— xhr.readyState
	是用来表示一个 ajax 请求的全部过程中的某一个状态
	readyState === 0: 表示未初始化完成,也就是 `open` 方法还没有执行
	readyState === 1:  表示配置信息已经完成,也就是执行完 `open` 之后
	readyState === 2:  表示 `send` 方法已经执行完成
	readyState === 3:  表示正在解析响应内容
	readyState === 4:  表示响应内容已经解析完毕,可以在客户端使用了
	这个时候我们就会发现,当一个 ajax 请求的全部过程中,只有当 `readyState === 4` 的时候,我们才可以正常使用服务端给我们的数据
	所以,配合 http 状态码为 200 ~ 299
		一个 ajax 对象中有一个成员叫做 `xhr.status` 
 		这个成员就是记录本次请求的 http 状态码的
 	两个条件都满足的时候,才是本次请求正常完成
三、readyStateChange
	在 ajax 对象中有一个事件,叫做 `readyStateChange` 事件
	这个事件是专门用来监听 ajax 对象的 `readyState` 值改变的的行为
	也就是说只要 `readyState` 的值发生变化了,那么就会触发该事件
	所以我们就在这个事件中来监听 ajax 的 `readyState` 是不是到 4 了
四、responseText
	ajax 对象中的 `responseText` 成员
	就是用来记录服务端给我们的响应体内容的
	所以我们就用这个成员来获取响应体内容就可以
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button>aaa</button>
    <script>
        var xhr = new XMLHttpRequest()

        xhr.open("get","1.json ",true)
        // 第一个参数 get post 请求方式
        // 第二个参数 请求地址
        // 第三个参数 是否异步

        xhr.send()

        // 监听
        // 方法一
        /* xhr.onreadystatechange = function() {
            console.log("电话接通");
            console.log(xhr.readyState); // 准备状态
            if(xhr.readyState === 4) {
                // if(xhr.status === 200) {
                if(/^2\d{2}$/.test(xhr.status)) {
                    console.log(JSON.parse(xhr.responseText))
                } else {
                    console.log("error",xhr.responseText);
                }
            }
        } */

        // 方法二
        xhr.onload = function() {
            if(/^2\d{2}$/.test(xhr.status)) {
                console.log(JSON.parse(xhr.responseText))
            } else {
                console.log("error",xhr.responseText);
            }
        }
    </script>
</body>
</html>
{
    "name":"xiaowang"
}

在这里插入图片描述

2.2 Ajax案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="btn">click</button>
    <ul id="list">
        
    </ul>
    <script>
        var obtn = document.querySelector('#btn')
        var olist = document.querySelector('#list')
        obtn.onclick = function() {
            var xhr = new XMLHttpRequest()

            xhr.open("get","http://www.xiongmaoyouxuan.com/api/tabs", true) // 后端接口地址

            xhr.send()

            xhr.onload = function() {
                if(/^2\d{2}$/.test(xhr.status)) {
                    // console.log(JSON.parse(xhr.responseText))
                    render(JSON.parse(xhr.responseText))
                } else {
                    console.log("error",xhr.responseText);
                }
            }
        }
        // 渲染页面
        function render(res) {
            console.log(res.data.list);

            var newlist = res.data.list.map(function(item){
                return `<li>
                    <img src="${item.imageUrl}"/>
                    <div>${item.name}</div>    
                </li>`
            })

            console.log(newlist);

            olist.innerHTML = newlist.JSON.join("")
        }
    </script>
</body>
</html>
{
    "data": {
        "list": [
            {
                "name": "假数据111",
                "imageUrl": "http://img1.lukou.com/static/p/fb/tab/1/20181211-151644.jpeg"
            },
            {
                "name": "假数据222",
                "imageUrl": "http://img1.lukou.com/static/p/fb/tab/1/20181211-151644.jpeg"
            },
            {
                "name": "假数据111",
                "imageUrl": "http://img1.lukou.com/static/p/fb/tab/1/20181211-151644.jpeg"
            },
            {
                "name": "假数据111",
                "imageUrl": "http://img1.lukou.com/static/p/fb/tab/1/20181211-151644.jpeg"
            }

        ]
    }
}

2.3 ajax请求方式

  • 不同的请求方式:
    1> get 偏向获取
    2> post 偏向提交
    3> put 偏向更新
    4> patch 偏向修改部分
    5> delete 偏向删除信息
    6> head 偏向获取服务器头的信息
    7> option 偏向获取服务器设备信息
    8> connect 保留请求方式

  • 使用get请求方式(不传参数):

oget.onclick = function() {
	var xhr = new XMLHttpRequest()
    xhr.open("GET","http://localhost:3000/list", true) // 后端接口地址
    xhr.send()
    xhr.onload = function() {
    	if(/^2\d{2}$/.test(xhr.status)) {
        	console.log(JSON.parse(xhr.responseText))
            // render(JSON.parse(xhr.responseText))
		} else {
        	console.log("error",xhr.responseText);
        }
	}
}
  • 使用get请求方式(传参数):
oget.onclick = function() {
	var xhr = new XMLHttpRequest()
    xhr.open("GET","http://localhost:3000/users?id=1", true)
    xhr.send()
    xhr.onload = function() {
    	if(/^2\d{2}$/.test(xhr.status)) {
        	console.log(JSON.parse(xhr.responseText))
            // render(JSON.parse(xhr.responseText))
		} else {
        	console.log("error",xhr.responseText);
        }
	}
}
  • 使用post请求方式(传参数):
opost.onclick = function() {
	var xhr = new XMLHttpRequest()
    xhr.open("POST","http://localhost:3000/users", true) // 后端接口地址
    // 两种提交方式:
    // form编码 name=kerwin&age=100
    // json {name:"kerwin",age:100}
    // 方式一
    /* xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")
    xhr.send(`name=tiechui&age=18`) */ // 数据放在这里
    // 方式二
    xhr.setRequestHeader("content-type","application/json")
    xhr.send(JSON.stringify({
    	name:"guludunzi",
        age:90
    })) // 数据放在这里
    xhr.onload = function() {
        if(/^2\d{2}$/.test(xhr.status)) {
        	console.log(JSON.parse(xhr.responseText))
            // render(JSON.parse(xhr.responseText))
        } else {
            console.log("error",xhr.responseText);
        }
	}
}
  • 使用put请求方式(传参数):
oput.onclick = function() {
    var xhr = new XMLHttpRequest()
    xhr.open("PUT","http://localhost:3000/users/4", true) // 后端接口地址
    // 两种提交方式:
    // form编码 name=kerwin&age=100
    // json {name:"kerwin",age:100}
    // 方式一
    /* xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")
    xhr.send(`name=tiechui&age=18`) */ // 数据放在这里
    // 方式二
    xhr.setRequestHeader("content-type","application/json")
    xhr.send(JSON.stringify({
        username:"guludunzi",
        age:70
    })) // 数据放在这里
    xhr.onload = function() {
        if(/^2\d{2}$/.test(xhr.status)) {
            console.log(JSON.parse(xhr.responseText))
            // render(JSON.parse(xhr.responseText))
        } else {
            console.log("error",xhr.responseText);
        }
    }
}
  • 使用patch请求方式(传参数):
opatch.onclick = function() {
    var xhr = new XMLHttpRequest()
    xhr.open("PATCH","http://localhost:3000/users/4", true) // 后端接口地址
    // 两种提交方式:
    // form编码 name=kerwin&age=100
    // json {name:"kerwin",age:100}
    // 方式一
    /* xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")
    xhr.send(`name=tiechui&age=18`) */ // 数据放在这里
    // 方式二
    xhr.setRequestHeader("content-type","application/json")
    xhr.send(JSON.stringify({
        // username:"guludunzi",
        age:180
    })) // 数据放在这里
    xhr.onload = function() {
        if(/^2\d{2}$/.test(xhr.status)) {
            console.log(JSON.parse(xhr.responseText))
            // render(JSON.parse(xhr.responseText))
        } else {
            console.log("error",xhr.responseText);
        }
    }
}
  • 使用delete请求方式(无参数):
odelete.onclick = function() {
    var xhr = new XMLHttpRequest()
    xhr.open("DELETE","http://localhost:3000/users/4", true) // 后端接口地址
    xhr.send()
    xhr.onload = function() {
        if(/^2\d{2}$/.test(xhr.status)) {
            console.log(JSON.parse(xhr.responseText))
            // render(JSON.parse(xhr.responseText))
        } else {
            console.log("error",xhr.responseText);
        }
    }
}

3 Fetch

  • XMLHttpRequest 是一个设计粗糙的 API,配置和调用方式非常混乱, 而且基于事件的异步模型写起来不友好。
  • 先在集成终端中打开json-server监视:
    在这里插入图片描述

3.1 fetch基础

  • 使用get请求方式(不传参数):
oget.onclick = function() {
    fetch("http://localhost:3000/users")
    .then(res =>res.json())
    .then(res => {
        console.log(res);
    })
}
  • 使用get请求方式(传参数):
oget.onclick = function() {
    fetch("http://localhost:3000/users?id=1")
    .then(res =>res.json())
    .then(res => {
        console.log(res);
    })
}
  • 使用post请求方式(传参数):
opost.onclick = function() {
    fetch("http://localhost:3000/users",{
        method:"post",
        headers:{
            // 两种提交方式:
            // form编码 name=kerwin&age=100
            // json {name:"kerwin",age:100}
            // 方式一
            // "content-type":"application/x-www-form-urlencoded"
            // 方式二
            "content-type":"application/json"
        },
        // body:"name=dazhuang&age=100" // 方式一body
        body:JSON.stringify({
            name:"xiaoli",
            age: 20
        })
    })
    .then(res =>res.json())
    .then(res => {
        console.log(res);
    })
}
  • 使用put请求方式(传参数):
oput.onclick = function() {
    fetch("http://localhost:3000/users/2",{
        method:"put",
        headers:{
            // 两种提交方式:
            // form编码 name=kerwin&age=100
            // json {name:"kerwin",age:100}
            // 方式一
            // "content-type":"application/x-www-form-urlencoded"
            // 方式二
            "content-type":"application/json"
        },
        // body:"name=dazhuang&age=100" // 方式一body
        body:JSON.stringify({
            name:"xiaowang",
            age: 76
        })
    })
    .then(res =>res.json())
    .then(res => {
        console.log(res);
    })
}
  • 使用patch请求方式(传参数):
opatch.onclick = function() {
    fetch("http://localhost:3000/users/2",{
        method:"PATCH",
        headers:{
            // 两种提交方式:
            // form编码 name=kerwin&age=100
            // json {name:"kerwin",age:100}
            // 方式一
            // "content-type":"application/x-www-form-urlencoded"
            // 方式二
            "content-type":"application/json"
        },
        // body:"name=dazhuang&age=100" // 方式一body
        body:JSON.stringify({
            age: 33
        })
    })
    .then(res =>res.json())
    .then(res => {
        console.log(res);
    })
}
  • 使用delete请求方式(无参数):
odelete.onclick = function() {
    fetch("http://localhost:3000/users/2",{
        method:"delete",
    })
    .then(res =>res.json())
    .then(res => {
        console.log(res);
    })
}
  • 以使用get请求方式为例失败处理:
oget.onclick = function() {
    fetch("http://localhost:3000/users?id=1")
    .then(res =>{
		if(res.ok){
			return res.json()
		}else{
			return Promise.reject({
				// 展示出错码和出错原因
				status:res.status,
				statusText:res.statusText
			})
		}
	})
    .then(res => {
        console.log(res);
    }).catch(err => {
		console.log("err", err)
	})
}

在这里插入图片描述

3.2 fetch案例

  • 通过输入作者姓名找到新闻标题,再根据新闻标题对应的新闻id找到所对应的评论内容。
  • db.json代码:
{
    "news": [
        { "id" : 1, "title" : "男人看了沉默,女人看了流泪", "author" : "kerwin"},
        { "id" : 2, "title" : "震惊!他年薪仅1元", "author" : "tiechui"},
        { "id" : 3, "title" : "速看!万分危急!", "author" : "gangdan"}
    ],
    "comments": [
        { "id" : 1, "body" : "我是男人", "newsId" : 1 },
        { "id" : 2, "body" : "我是女人", "newsId" : 1 },
        { "id" : 3, "body" : "我年薪2元", "newsId" : 2 },
        { "id" : 4, "body" : "我年薪3元", "newsId" : 2 },
        { "id" : 5, "body" : "1块钱就能买1块钱的东西", "newsId" : 3 },
        { "id" : 6, "body" : "2块钱就能买2块钱的东西", "newsId" : 3 }
    ]
}
  • 基于fetch的01.html代码:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="text" id="search">
    <h1 id="title"></h1>
    <ul id="list"></ul>
    <script>
        var osearch = document.querySelector('#search')
        var otitle = document.querySelector('#title')
        var olist = document.querySelector('#list')

        osearch.oninput = function() {
            fetch(`http://localhost:3000/news?author=${osearch.value}`)
            .then( res => res.json())
            .then( res => {
                if(res.length > 0) {
                    otitle.innerHTML = res[0].title
                    return fetch(`http://localhost:3000/comments?newsId=${res[0].id}`)
                    .then(res=>res.json())
                }else {
                    otitle.innerHTML = ""
                    return res
                }
            }).then(res=>{
                console.log(res)
                olist.innerHTML = res.map( item => `
                    <li>
                        ${item.body}
                    </li>
                `).join("") // join是为了避免中间有逗号
            })
        }
    </script>
</body>
</html>
  • fetch结合async await下的01.html代码:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="text" id="search">
    <h1 id="title"></h1>
    <ul id="list"></ul>
    <script>
        var osearch = document.querySelector('#search')
        var otitle = document.querySelector('#title')
        var olist = document.querySelector('#list')

        osearch.oninput = async function() {
            var res = await fetch(`http://localhost:3000/news?author=${osearch.value}`)
            .then( res => res.json())
            var result
            if(res.length > 0) {
                otitle.innerHTML = res[0].title
                result = await fetch(`http://localhost:3000/comments?newsId=${res[0].id}`)
                .then(res=>res.json())
            }else {
                otitle.innerHTML = ""
                result = res
            }
            // console.log("111",result)
            olist.innerHTML = result.map( item => `
                <li>
                    ${item.body}
                </li>
            `).join("") // join是为了避免中间有逗号
        }
    </script>
</body>
</html>

在这里插入图片描述

4 axios

  • Axios是一个基于promise 的 HTTP 库,可以用在浏览器和 node.js中。
  • https://www.npmjs.com/package/axios

4.1 axios基础

  • 使用get请求方式(不传参数):
oget.onclick = function() {
	axios.get("http://localhost:3000/users")
    // 若成功走.then
    .then(res => {
    	console.log(res.data)
     })
     // 若失败走.catch
     .catch(err => {
        console.log("err",err)
     })
}
  • 使用get请求方式(传参数):
oget.onclick = function() {
	axios.get("http://localhost:3000/users?name=kerwin")
    // 若成功走.then
    .then(res => {
    	console.log(res.data)
     })
     // 若失败走.catch
     .catch(err => {
        console.log("err",err)
     })
}
  • 使用get请求方式(传参数且为对象结构):
oget.onclick = function() {
	axios.get("http://localhost:3000/users",{
		params:{
			name:"kerwin"
		}
	})
    // 若成功走.then
    .then(res => {
    	console.log(res.data)
     })
     // 若失败走.catch
     .catch(err => {
        console.log("err",err)
     })
}
  • 使用post请求方式(传参数):
 opost.onclick = function() {
	// 以json方式传参数
	/* axios.post("http://localhost:3000/users",{
    	name:"xiaoming",
        age:18
    }) */
    
    // 以form方式传参数方法一
    // axios.post("http://localhost:3000/users","name=tiechui&age=77")

	// 以form方式传参数方法二
	const params = new URLSearchParams({name:"dazhuang",age:13});
    axios.post("http://localhost:3000/users",params)

	// 若成功走.then
    .then(res => {
    	console.log(res.data)
    })
    // 若失败走.catch
    .catch(err => {
    	console.log("err",err)
    })
}
  • 使用put请求方式(传参数):
oput.onclick = function() {
	axios.put("http://localhost:3000/users/4",{
    	name:"dazhuang",
        age:99
    })
    // 若成功走.then
    .then(res => {
    	console.log(res.data)
    })
    // 若失败走.catch
    .catch(err => {
    	console.log("err",err)
    })
}
  • 使用patch请求方式(传参数):
opatch.onclick = function() {
	axios.patch("http://localhost:3000/users/4",{
        age:101
    })
    // 若成功走.then
    .then(res => {
    	console.log(res.data)
    })
    // 若失败走.catch
    .catch(err => {
    	console.log("err",err)
    })
}
  • 使用delete请求方式(无参数):
odelete.onclick = function() {
	axios.delete("http://localhost:3000/users/4")
    // 若成功走.then
    .then(res => {
    	console.log(res.data)
	})
    // 若失败走.catch
    .catch(err => {
        console.log("err",err)
    })
}
  • axios(config)配置:
axios({
	method:"post",
	url:'http://localhost:3000/users',
	// put post等放入data中 get放入params中
	data:{
		name:'kerwin',
		age: 88
	}
})
.then(res => {
	console.log(res.data)
})
.catch(err => {
	console.log(err)
})

4.2 axios使用

4.2.1 axios拦截器

  • db.json代码:
{
  "news": [
      { "id" : 1, "title" : "男人看了沉默,女人看了流泪", "author" : "kerwin"},
      { "id" : 2, "title" : "震惊!他年薪仅1元", "author" : "tiechui"},
      { "id" : 3, "title" : "速看!万分危急!", "author" : "gangdan"}
  ],
  "comments": [
      { "id" : 1, "body" : "我是男人", "newsId" : 1 },
      { "id" : 2, "body" : "我是女人", "newsId" : 1 },
      { "id" : 3, "body" : "我年薪2元", "newsId" : 2 },
      { "id" : 4, "body" : "我年薪3元", "newsId" : 2 },
      { "id" : 5, "body" : "1块钱就能买1块钱的东西", "newsId" : 3 },
      { "id" : 6, "body" : "2块钱就能买2块钱的东西", "newsId" : 3 }
  ]
}
  • 01.html代码:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入axios -->
    <script src="https://cdn.jsdelivr.net/npm/axios@1.1.2/dist/axios.min.js"></script>
</head>
<body>
    <button id="get">get</button>
    <script>
        var oget = document.querySelector("#get")

        // axios拦截器
        // request请求拦截器
        axios.interceptors.request.use(function (config) {
            // Do something before request is sent
            // console.log("loading-开始")
            console.log("loading显示....")
            return config;
        }, function (error) {
            // Do something with request error
            return Promise.reject(error);
        });

        // response响应拦截器
        // Add a response interceptor
        axios.interceptors.response.use(function (response) {
            // Any status code that lie within the range of 2xx cause this function to trigger
            // Do something with response data
            // 成功响应拦截器
            // console.log("loading-结束")
            console.log("成功-隐藏loading....")
            return response;
        }, function (error) {
            // Any status codes that falls outside the range of 2xx cause this function to trigger
            // Do something with response error
            // 失败响应拦截器
            // console.log("loading---结束")
            console.log("失败-隐藏loading....")
            return Promise.reject(error);
        });

        oget.onclick = function() {
            axios.get('http://localhost:3000/news').then(res => {
                console.log(res.data);
            }).catch(err => {
                console.log("err",err);
            })
        }
    </script>
</body>
</html>

在这里插入图片描述
在这里插入图片描述

4.2.2 axios中断器

const controller = new AbortController();

axios.get('/foo/bar', {
   signal: controller.signal
}).then(function(response) {
   //...
});
// cancel the request
controller.abort()
  • 01.html代码:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入axios -->
    <script src="https://cdn.jsdelivr.net/npm/axios@1.1.2/dist/axios.min.js"></script>
</head>
<body>
    <button id="get">get</button>
    <!-- 终止按钮 -->
    <button id="abort">abort</button>
    <script>
        var oget = document.querySelector("#get")
        var oabort = document.querySelector("#abort")

        // axios拦截器
        // request请求拦截器
        axios.interceptors.request.use(function (config) {
            // Do something before request is sent
            // console.log("loading-开始")
            console.log("loading显示....")
            return config;
        }, function (error) {
            // Do something with request error
            return Promise.reject(error);
        });

        // response响应拦截器
        // Add a response interceptor
        axios.interceptors.response.use(function (response) {
            // Any status code that lie within the range of 2xx cause this function to trigger
            // Do something with response data
            // 成功响应拦截器
            // console.log("loading-结束")
            console.log("成功-隐藏loading....")
            return response;
        }, function (error) {
            // Any status codes that falls outside the range of 2xx cause this function to trigger
            // Do something with response error
            // 失败响应拦截器
            // console.log("loading---结束")
            console.log("失败-隐藏loading....")
            return Promise.reject(error);
        });

        // axios中断器
        const controller = new AbortController();

        oget.onclick = function() {
            axios.get('http://localhost:3000/news',{
                signal: controller.signal
            })
            .then(res => {
                console.log(res.data);
            }).catch(err => {
                console.log("err",err);
            })
        }

        oabort.onclick = function() {
            controller.abort()
        }
    </script>
</body>
</html>

在这里插入图片描述

5 同源策略

  • 一个URL有三部分组成:协议、域名(指向主机)、端口,只有这三个完全相同的 URL 才能称之为同源。
  • 如下,能和http://www.example.com/dir1/index.html 同源的是?
    在这里插入图片描述
  • 无法读取非同源网页的 Cookie、LocalStorage 。
  • 无法接触非同源网页的 DOM。
  • 无法向非同源地址发送 AJAX 请求(可以发送,但浏览器会拒绝接受响应)。
  • 注意:同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。

6 解决跨域

6.1 jsonp

  • Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。
  • 为什么我们从不同的域(网站)访问数据需要一个特殊的技术( JSONP )呢?这是因为同源策略。
  • 1.txt代码:
test("xiaowang")
  • 01.html代码:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function test(data){
            console.log("111",data);
        }


        var oscript = document.createElement("script")
        oscript.src = "1.txt"
        document.body.appendChild(oscript)

        // 1.script标签没有跨域限制
        // 2.后端配合返回的是 函数() 调用的方式
        // 3.前端必须提前声明好这个函数

        // 缺点:jsonp只能get请求 无法post、put、delete
    </script>
    <!-- <script>
        // <script src="1.txt">
        // test("xiaowang")
    </script> -->
</body>
</html>

在这里插入图片描述

  • 案例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="text" id="search">
    <ul id="list">

    </ul>

    <script>
        var osearch = document.querySelector('#search')
        var olist = document.querySelector('#list')

        osearch.oninput = function(){
            // console.log(osearch.value)
            if(osearch.value === "") {
                olist.innerHTML = ""
                return
            }
            var oscript = document.createElement("script")
            oscript.src = `https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web&sugsid=39646,39671,39663,39676,39678,39713,39791,39787,39704,39793,39681,39662&wd=${osearch.value}&req=2&csor=1&cb=test&_=1700639132336`
            document.body.appendChild(oscript)

            oscript.onload = function() {
                oscript.remove() // 创建完script标签 等它load完了 就给它移掉
            }
        }

        function test(data) {
            // console.log(data.g);
            olist.innerHTML = data.g.map(item => 
                `
                    <li>${item.q}</li>
                `
            ).join("")
        }
    </script>
</body>
</html>

在这里插入图片描述

6.2 其他技术手段

  • 加上响应头
  • 反向代理nginx跨域解决方案

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1245944.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【每日一题】2824. 统计和小于目标的下标对数目-2023.11.24

题目&#xff1a; 2824. 统计和小于目标的下标对数目 给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 target &#xff0c;请你返回满足 0 < i < j < n 且 nums[i] nums[j] < target 的下标对 (i, j) 的数目。 示例 1&#xff1a; 输入&#xff1…

Digicert通配符证书:满足你的所有需求

通配符证书是一种可以保护一个主域名及其所有子域名的SSL证书。这意味着&#xff0c;如果你有一个主域名&#xff0c;比如www.example.com&#xff0c;并且你有多个子域名&#xff0c;比如blog.example.com、store.example.com等&#xff0c;那么只需要一个通配符证书&#xff…

ubuntu22.04系统下载程序和依赖,并拷贝到指定路径下

脚本1 apt install aptitude apt-get -d install xxx #xxx是待下载的安装包 mv /var/cache/apt/archives/* /home/tuners/1apt install aptitude apt-get -d install xxx mv /var/cache/apt/archives/*.deb /home/tuners/1 xxx 为程序包名称 /home/tuners/1为保存程序包的…

阿里云windwos 安装oracle数据库,外部用工具连接不上,只能在服务器本机通过127.0.0.1 连接

1. 首先检查阿里云服务器安全组端口是否开放 oracle 数据库端口 2. 其次找到oracle 安装的目录&#xff0c;打开这俩个文件&#xff0c;将localhost 修改为 服务器本机名称 3.重启oracle 监听服务&#xff0c;就可以连接了

IBM SPSS Statistics 27 Mac(统计分析软件)

IBM SPSS Statistics是一款数据分析和统计建模软件&#xff0c;它专为研究人员、分析师和商业用户设计。该软件能够帮助用户对大量数据进行分析和预测&#xff0c;帮助用户制定决策和解决问题。 IBM SPSS Statistics提供了丰富的统计分析功能&#xff0c;包括描述性统计、相关性…

【鸿蒙应用ArkTS开发系列】- 云开发入门实战二 实现省市地区三级联动地址选择器组件(下)

文章目录 概述端云调用流程端侧集成AGC SDK端侧省市地区联动的地址选择器组件开发创建省市数据模型创建省市地区视图UI子组件创建页面UI视图Page文件 打包测试总结 概述 我们在前面的课程&#xff0c;对云开发的入门做了介绍&#xff0c;以及使用一个省市地区联动的地址选择器…

IDM(Internet Download Manager)PC版提升下载速度与效率的利器

你是否曾经因为下载速度慢而感到烦恼&#xff1f;或者在下载大型文件时&#xff0c;经历了长时间的等待&#xff1f;如果你有这样的困扰&#xff0c;那么IDM&#xff08;Internet Download Manager&#xff09;就是你的救星&#xff01; IDM是一款高效、实用的下载管理器&…

PS 计数工具 基础使用方式讲解

上文PS 注释工具 基础使用方法讲解 中 我们讲了注释工具 解析来 我们来看这个计数工具 这里 我们换一张图像 如果 我要你数清楚 这个图上有几个咖啡豆 你能数清楚吗&#xff1f; 哈哈 其实也不难 不是特别大 但是 例如很多 且无规则物品时 我们可能就会数乱 左上角属性的话 我…

vue2【组件的构成】

目录 1&#xff1a;什么是组件化开发 2&#xff1a;vue中的组件化开发 3&#xff1a;vue组件的三个组成部分 4&#xff1a;组件中定义方法&#xff0c;监听器&#xff0c;过滤器&#xff0c;计算属性节点。 5&#xff1a;template中只允许唯一根节点&#xff0c;style默认…

arp报文及使用go实现

一、ARP协议报文格式及ARP表 ARP&#xff08;Address Resolution Protocal&#xff0c;地址解析协议&#xff09;是将IP地址解析为以太网的MAC地址&#xff08;或者称为物理地址&#xff09;的协议。在局域网中&#xff0c;当主机或其他网络设备有数据要发送给另一个主机或设备…

【2023年APMCM亚太杯C题】完整数据与解题思路

2023年亚太杯C题 数据下载与搜集重点数据其余数据第一问第二问第三问第四问第五问第六问 数据与思路获取 数据下载与搜集 该题并没有提供数据集&#xff0c;对所需数据进行收集整理是对题目进行求解的基础。在本题中&#xff0c;主要需要以下数据&#xff1a;新能源汽车历史销…

(免费领源码)java#springboot#mysql流浪动物救助系统78174-计算机毕业设计项目选题推荐

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

知行之桥EDI系统HTTP签名验证

本文简要概述如何在知行之桥EDI系统中使用 HTTP 签名身份验证&#xff0c;并将使用 CyberSource 作为该集成的示例。 API 概述 首字母缩略词 API 代表“应用程序编程接口”。这听起来可能很复杂&#xff0c;但真正归结为 API 是一种允许两个不同实体相互通信的软件。自开发以…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于外部性理论的网侧储能成本疏导机制研究》

这个标题涉及到一个关于储能的研究&#xff0c;主要聚焦在基于外部性理论的网侧&#xff08;电网侧&#xff09;储能成本疏导机制上。 基于外部性理论&#xff1a; 这表明研究的框架或者理论基础是"外部性理论"。外部性是指某个经济活动的影响不仅限于直接参与者&…

Adobe的组织工具程序Bridge 2024 版本下载与安装

目录 前言一、Bridge 2024安装二、使用配置总结 前言 Adobe Bridge是由 Adobe 公司开发的一款用于管理和组织创意资产的工具。它是Adobe Creative Cloud 套件的一部分&#xff0c;为设计师、摄影师和其他创意专业人员提供了一个集中管理和浏览其多媒体文件的平台。注&#xff…

JVM类加载的过程和JVM垃圾回收机制

文章目录 一、JVM类加载的过程1.1类加载的基本流程1.1.1加载1.1.2验证1.1.3准备1.1.4解析1.1.5初始化 1.2双亲委派模型 二、JVM垃圾回收机制2.1找到垃圾2.1.1引用计数(比如Python&#xff0c;PHP中用到)2.1.2可达性分析(比如Java中用到) 2.2释放垃圾2.2.1标记清除2.2.2复制算法…

小程序中的大道理--综述

前言 以下将用一个小程序来探讨一些大道理, 这些大道理包括可扩展性, 抽象与封装, 可维护性, 健壮性, 团队合作, 工具的利用, 可测试性, 自顶向下, 分而治之, 分层, 可读性, 模块化, 松耦合, MVC, 领域模型, 甚至对称性, 香农的信息论等等. 为什么不用大程序来说大道理呢? …

python写文件

output_file open(E:/XD_transfer/代码/CNN_new/try.csv, w) output_file.write(Sample, \n) for j in range(5):output_file.write(str(j) \n)

1-docker安装和配置、虚拟化、配置国内源、镜像操作、容器基本操作(run运行容器、-v目录映射、-p端口映射、容器其他操作)

1 docker和虚拟化 2 docker安装和配置 2.0 docker 中的一些概念 2.1 配置镜像加速器&#xff08;国内源&#xff09; 3 镜像操作 4 容器操作 4.1 容器基本操作 4.2 run运行容器 4.3 -v目录映射 4.4 -p端口映射 4.5 容器其他操作 1 docker和虚拟化 ## 什么是虚拟化在计算机中&…

数十亿美元商机!英国数字基础设施公司Equinix与法国量子计算公司Alice Bob 合作

​&#xff08;图片来源&#xff1a;网络&#xff09; 近日&#xff0c;全球数字基础设施公司Equinix宣布与全球领先的法国量子计算公司Alice & Bob合作&#xff0c;旨在共同开发市场上最为可靠的量子处理器之一。此次合作将使Equinix公司的客户通过使用Equinix Metal和Eq…