Express补充
Express返回json
express的resp可以渲染对象,也可以send字符串,我们可以将一个对象通过JSON.stringify()
序列化成json字符串以后再通过resp.send()
发送到页页去
如果前端需要我们设置CORS跨域的时候,服务器应该怎么设置呢
app.js代码
app.get("/getList", (req, resp) => {
let obj = {
userName: "杨标",
sex: "男",
age: 18,
hobby: ["看书", "睡觉"]
};
let jsonStr=JSON.stringify(obj); //将对象序列化成json字符串
resp.setHeader("Access-Control-Allow-Headers","Content-Type");
resp.setHeader("Access-Control-Allow-Methods","GET,POST,PUT,DELETE,OPTIONS");
resp.setHeader("Access-Control-Allow-Origin","*");
resp.send(jsonStr);
});
在服务器里面,我们将得到的obj对象通过JSON.stringify(obj)
变成了json字符串,然后调用resp.send()
的方法发送到的浏览器,浏览器通过 ajax接收到的就是一个json字符串,它是一个 string
,如果需要使用,需要在浏览器调用JSON.parse()
重新转化成js对象
浏览器代码
$(function(){
$("#btn1").click(function(){
$.get("http://127.0.0.1:8888/getList",function(data){
// data 就是服务器返回的数据
console.log(data);
console.log(typeof data); //string
//如果要拿到里面的属性,应该怎么办
var jsonObj = JSON.parse(data);
console.log(typeof jsonObj); //object
console.log(jsonObj.userName);
});
});
})
在之前我们使用Ajax请求的时候,我们返回的都是一个对象,不需要我们调用JSON.parse()
的方法去转换。现在我们的服务器为什么不行呢
通过上面的图,我们可以看一以,在服务器里面,我们把对象转成JSON字符串,而在浏览器里面,我们又把JSON字符串成了对象
当我们如果在调用resp.send()
返回之前,如果添加了如下的响应头
resp.setHeader("Content-Type","application/json");
则前端在接收到的时候,数据会自动的做一次JSON.parse()
的转换,这个时候,得到的就是一个js对象
添加请求头以后的代码
app.get("/getList2",(req,resp)=>{
let obj = {
userName: "杨标",
sex: "男",
age: 18,
hobby: ["看书", "睡觉"]
};
resp.setHeader("Access-Control-Allow-Headers","Content-Type");
resp.setHeader("Access-Control-Allow-Methods","GET,POST,PUT,DELETE,OPTIONS");
resp.setHeader("Access-Control-Allow-Origin","*");
let jsonStr=JSON.stringify(obj); //将对象序列化成json字符串
//添加一个响应类型
resp.setHeader("Content-Type","application/json");
resp.send(jsonStr);
});
所以通过Ajax去接收的时候,一定要注意返回的数据到底是什么类型,如果是JSON字符串,则要手动的做一次转换,如果是对象则不用转了
这一种方式虽然简化了前面的操作,但在是在Express里面又多了一步操作,所以Express考虑到这种情况以后,直接推了一个新的方法resp.json();
app.get("/getList3",(req,resp)=>{
let obj = {
userName: "杨标",
sex: "男",
age: 18,
hobby: ["看书", "睡觉"]
};
resp.setHeader("Access-Control-Allow-Headers","Content-Type");
resp.setHeader("Access-Control-Allow-Methods","GET,POST,PUT,DELETE,OPTIONS");
resp.setHeader("Access-Control-Allow-Origin","*");
//没有设置请头,直接把对象放了进去
resp.json(obj);
})
resp.json()
这个方法相当于把对象序列化成JSON字符串以后然后再给它添加一个application/json
的请求头,这个前端在接收到数据的时候,就直接是一个对象了,不需要在转换了
这种操作既方便了后端,也方便了前端。所以后期在Express里面需要返回一个JSON字符串到前端去的时候,可以调用这个方法
通过拦截器来设置请求头
在上面的三个请求里面, 我们每次都设置了跨域的请求头,这样很麻烦 ,我们可以利用之前学习的Express拦截器来完成这个操作
//添加一个拦截器,给响应的请求添加请求头
app.use((req,resp,next)=>{
resp.setHeader("Access-Control-Allow-Headers","Content-Type");
resp.setHeader("Access-Control-Allow-Methods","GET,POST,PUT,DELETE,OPTIONS");
resp.setHeader("Access-Control-Allow-Orogin","*");
//放行
next();
})
只需要所有的请求前面添加上面的拦截器,这样所有请求的返回就都可以添加上面的请求头了
Express的请求方式
就目前我们所学习的app与路由的处理请求方式里面,有app.get(),app.post()
express里面,get请求的参数通过req.query
的方式获取,post请求的方式req.body
router.get("/List",(req,resp)=>{
console.log(req.query);
})
router.post("/List",(req,resp)=>{
console.log(req.body);
});
不同的请求方式对应不同的取值方式
路径变量pathVariable
字变意义理解就是把变量放在请求路径里面去
router.get("/checkSid/:sid",(req,resp)=>{
let arr=["1001","1002","1003"];
// let sid=req.params.sid;
let {sid}=req.params;
console.log(sid);
resp.send(arr.includes(sid));
})
这个时候,前端的请求地址就应该变成 http://127.0.0.1:8888/StuInfo/checkSid/1001
,最后面的1001
代表路径变量参数:sid
路径变量的参数取值使用req.params
来进行
路径变量还可以放多个参数
router.get("/checkSid/:sid/:userName",(req,resp)=>{
let arr=["1001","1002","1003"];
// let sid=req.params.sid;
let {sid,userName}=req.params;
console.log(sid);
console.log(userName);
resp.send(arr.includes(sid));
})
请求的url为http://127.0.0.1:8888/StuInfo/checkSid/1001/yangbiao
优点
- 定义了参数以后必须要传递参数,如果不传,找不到路径,报404错误
- 这一种请求方式既可以以路径变量的方式向后台传值 ,也可以以post的方式向后后,一次请求,两种传递方式。如下代码所示
router.post("/doCheckSid/:sid/:userName",(req,resp)=>{
console.log(req.params);
console.log(req.body);
resp.send("我收到你的数据了");
});
这个地方的 sid与userName是通过路径变量传递过来的,而后面的其它参数则是通过post传递过来的
Express的多功能请求方式
当一个路由需要通过多各请求方式接收路径请求的时候,我们建议它使用all
的方法。如下代码
router.all("/test",(req,resp)=>{
// console.log(req.query.sid);
let sid = req.param("sid");
let sname=req.param("sname");
console.log(sid,sname);
resp.send("我收到test的数据了");
});
all可以接收所有的请求类型,但是在接收值的方面,我们更建议使用 req.param()
的方法来接值,这种接值是不针对请求方式,只要你传值了,无论以何种方式进来的,一定可以接收到
Express接收前端传值总结
传值方式 | 服务器接收值方式 | 备注 |
---|---|---|
router.get("/List") | req.query | |
router.post("/List") | req.body | |
router.get("/List/:sid") | req.params | pathVariable具体参照上个章节 |
router.all("/List") | req.param() | 这是一个方法,可以接收任何方式传过来的值 |
Express实现中转服务器
在前端的ajax请求里面,我们的ajax是不允许跨域请求数据的,这个时候,我们可以使用nodejs来进行一次中转操作
第一步:创建路由
app.use("/maoyanApi",require("./routes/maoyanApiRoute"));
第二步:在路由里建议代理
const router=require("express").Router();
const axios=require("axios");
let baseURL="http://m.maoyan.com"; //原始的地址就是这一个
router.all(/\/.*/,async (req,resp)=>{
let method=req.method; //得到请求方式
let url = req.url; //这个地址不包含路由的路径 maoyanApi
let result=null;
if(method.toUpperCase()=="GET"){
result = await axios.default.get(baseURL+url,{
responseType:"stream"
});
}
else if(method.toUpperCase()=="POST"){
result= await axios.default.post(baseURL+url,req.body,{
responseType:"stream"
});
}
// resp.send(JSON.stringify(result.data));
result.data.pipe(resp);
});
module.exports=router;
- router.all()代表接收所有的请求方式
/\/.*/
这个正则代表接收所有的请求路径- 使用流的方式响应数据,然后以流的信息直接对接到
resp
上面
当代码完成以后,我们就可以实现请求代理了
新地址
http://127.0.0.1:8888/maoyanApi/ajax/comingList?token=
原地址
http://m.maoyan.com/ajax/comingList?token=
评论区