HTTP fetch发送2次请求的原因?面对这道出现频率较高的面试题,我想说的是:发送两次请求的情况确实存在,但这与你所使用的是不是http协议,所采用的是不是fetch真的没有一毛钱关系!

接下来,咱们可以通过代码一一去验证……

一、准备工作

1、创建一个文件夹zhangpeiyue

2、在zhangpeiyue文件夹内创建两个文件:server.jsindex.html

server.js:搭建一个express服务器,用于提供接口•index.html:通过fetch调用接口。

二、前后端符合同源策略的场景

1、通过server.js创建服务:

const express = require("express");// 通过 body-parser 接收 post 过来的数据const bodyParser = require("body-parser");const app = express();// 接收 post 的数据为 application/json 格式app.use(bodyParser.json());// 将当前文件夹设置为静态资源app.use(express.static(__dirname));app.post("/my",(req,res)=>{    res.json({        ok:1,        body:req.body// 将接收到的数据返回给前端    })});app.listen(80,(err)=>{    console.log("success");})

2、启动服务

node server

3、index.html嵌入js:

// 为避免出现缓存,增加 t 参数fetch("http://127.0.0.1/my?t="+Date.now(),{    method:"post",    body:JSON.stringify({        a:1,        b:2    }),    headers:{        "content-type":"application/json"    }}).then(res=>res.json())    .then(response=>console.log("Success:",response))    .catch(error=>console.log("Error",error))

4、浏览器打开http://127.0.0.1测试


5、结论

• 在同源的情况下并未出现请求两次的情况

三、fetch在跨域的情况下

1、server.js修改如下:

const express = require("express");// 通过 body-parser 接收 post 过来的数据const bodyParser = require("body-parser");const app = express();// 接收 post 的数据为 application/json 格式app.use(bodyParser.json());// 将当前文件夹设置为静态资源app.use(express.static(__dirname));app.all("*",(req,res,next)=>{    console.log(req.method);    res.set({        "Access-Control-Allow-Origin":"*",        "Access-Control-Allow-Headers":"content-type"    })    next();})app.post("/my",(req,res)=>{    res.json({        ok:1,        body:req.body// 将接收到的数据返回给前端    })});app.listen(80,(err)=>{    console.log("success");})

2、将前端content-type设置为application/json,然后通过开发工具的http方式在浏览器打开index.html,或自己重新创建一个服务,在浏览器打开index.html。你会发现其果然请求了两次,分别为OPTIONS请求与POST请求:

// 为避免出现缓存,增加 t 参数fetch("http://127.0.0.1/my?t="+Date.now(),{    method:"post",    body:JSON.stringify({        a:1,        b:2    }),    headers:{        "content-type":"application/json"    }}).then(res=>res.json())    .then(response=>console.log("Success:",response))    .catch(error=>console.log("Error",error))

•请求方式:OPTIONS


•请求方式:POST


3、将js代码中的content-type注释掉,然后在非同源的场景下再次访问,你会发现只发送了一次post请求。

// 为避免出现缓存,增加 t 参数fetch("http://127.0.0.1/my?t="+Date.now(),{    method:"post",    body:JSON.stringify({        a:1,        b:2    }),    headers:{        // "content-type":"application/json"    }}).then(res=>res.json())    .then(response=>console.log("Success:",response))    .catch(error=>console.log("Error",error))

•只发送了post请求:


4、将content-type更改为application/x-www-form-urlencoded,再次访问,依然只发送了一次POST请求:

// 为避免出现缓存,增加 t 参数fetch("http://127.0.0.1/my?t="+Date.now(),{    method:"post",    body:JSON.stringify({        a:1,        b:2    }),    headers:{        "content-type":"application/x-www-form-urlencoded"    }}).then(res=>res.json())    .then(response=>console.log("Success:",response))    .catch(error=>console.log("Error",error))

•只发送了post请求:


5、将fetch改为XMLHttpRequest。将content-type设置为application/json。打开index.html,此时会请求两次,分别为OPTIONS请求与POST请求:

const xhr = new XMLHttpRequest();xhr.open("post","http://127.0.0.1/my?t="+Date.now());xhr.setRequestHeader("content-type","application/json")xhr.send(JSON.stringify({a:1,b:2}));xhr.onload = function () {    console.log(xhr.responseText)}

•请求方式:OPTIONS


•请求方式:POST


6、将配置content-type的代码注释掉,结果只发送了一次POST请求:

const xhr = new XMLHttpRequest();xhr.open("post","http://127.0.0.1/my?t="+Date.now());// xhr.setRequestHeader("content-type","application/json")xhr.send(JSON.stringify({a:1,b:2}));xhr.onload = function () {    console.log(xhr.responseText)}

•请求方式:POST


四、接口的协议为https:

1、server.js

const express = require("express");// 通过 body-parser 接收 post 过来的数据const bodyParser = require("body-parser");const https = require("https");const fs = require("fs");const app = express();// 创建 https 服务,需要证书与密钥(需要有自己的域名)const httpsServer = https.createServer({    key:fs.readFileSync(__dirname+"/key/weixin.key"),    cert:fs.readFileSync(__dirname+"/key/weixin.crt")},app)// 接收 post 的数据为 application/json 格式app.use(bodyParser.json());app.all("*",(req,res,next)=>{    console.log(req.method);    res.set({        "Access-Control-Allow-Origin":"*"    })    next();})app.post("/my",(req,res)=>{    res.json({        ok:1,        body:req.body// 将接收到的数据返回给前端    })});httpsServer.listen(443,()=>{    console.log("httpsServer->success")})

2、content-type设置为application/json,然后以http的形式打开页面。结果会请求两次,分别为OPTIONS请求与POST请求:

// 为避免出现缓存,增加 t 参数fetch("https://weixin.zhangpeiyue.com/my?t="+Date.now(),{    method:"post",    body:JSON.stringify({        a:1,        b:2    }),    headers:{        "content-type":"application/json"    }}).then(res=>res.json())    .then(response=>console.log("Success:",response))    .catch(error=>console.log("Error",error))

•请求方式:OPTIONS


•请求方式:POST


五、总结

发送2次请求需要满足以下2个条件:

1、必须要在跨域的情况下。    2、除GET、HEAD和POST(only with application/x-www-form-urlencoded, multipart/form-data, text/plain Content-Type)以外的跨域请求(我们可以称为预检(Preflighted)的跨域请求)。

最后,建议大家可以这样回复面试官:之所以会发送2次请求,那是因为我们使用了带预检(Preflighted)的跨域请求。该请求会在发送真实的请求之前发送一个类型为OPTIONS的预检请求。预检请求会检测服务器是否支持我们的真实请求所需要的跨域资源,唯有资源满足条件才会发送真实的请求。比如我们在请求头部增加了authorization项,那么在服务器响应头中需要放入Access-Control-Allow-Headers,并且其值中必须要包含authorization,否则OPTIONS预检会失败,从而导致不会发送真实的请求。


分享就到这里了,如果这篇文章对你有所帮助的话,欢迎点赞、转发、点再看,在此谢过~

winform接收http请求_web前端面试题对答篇:HTTP fetch发送2次请求的原因?相关推荐

  1. http协议修改js或html,web前端面试题对答篇:HTTP fetch发送2次请求的原因?

    web前端面试题对答篇:HTTP fetch发送2次请求的原因? 2020-08-31 04:36:44 289 编程开发 HTTP fetch发送2次请求的原因?面对这道出现频率较高的面试题,我想说 ...

  2. web前端面试题对答篇:谈谈你对Promise的理解

    回答这个问题时,个人不建议单纯的从Promise的细节知识点答起,因为这个问题的本质是拥有一定宏观性的,如果仅仅回复一些知识点恐怕是满足不了面试官胃口的. 当然,如果这个问题回答不到点上,那么后续面试 ...

  3. 详细前端面试题javascript篇--持续更新

    最新前端面试题汇总大全(超详细含vue,react,css,js,webpack,性能优化等)–持续更新点击查看 前端HTML篇 前端CSS篇 前端面试题js篇--持续更新 1. JS 数据类型 ?存 ...

  4. 前端面试题-JavaScript篇

    web前端面试题 JavaScript篇 1.JavaScript的数据类型都有哪些(8条)? ES5中有6种:Number.String.Boolean.Undefined.Null.Object ...

  5. 前端面试题 ---- html篇

    前端面试题 ---- html篇 想要换工作了,转载自https://www.cnblogs.com/zhangshuda/p/8464772.html,感谢原博主. 一.html 1.html和xh ...

  6. 详细前端面试题HTML篇

    CSS篇 JS篇 Vue篇 TypeScript篇 React篇 微信小程序篇 前端面试题汇总大全(含答案超详细,HTML,JS,CSS汇总篇)-- 持续更新 前端面试题汇总大全二(含答案超详细,Vu ...

  7. 播放失败246106异常代码_web前端面试题:您能读懂的Promise源码实现(手写代码)...

    Promise 是 web 前端工程师在面试的过程中很难绕过的一个坎.如果您目前处于对 Promise 一知半解,或仅仅是停留在可以使用的层面上,建议您跟着本文敲打练习一遍,相信您一定会有所收获!另外 ...

  8. 前端面试题js篇,持续更新

    1.解释重绘与回流,以及如何优化? 重绘与回流:   在页面加载时,浏览器会把获取到的html代码解析成dom树,dom树中包含html所有标签以及js动态生成的元素等.浏览器会把所有的样式(即css ...

  9. 2023前端面试题——JS篇

    1.判断 js 类型的方式 1. typeof 可以判断出'string','number','boolean','undefined','symbol' 但判断 typeof(null) 时值为 ' ...

最新文章

  1. Nodejs 环境配置终极解决方案
  2. Latent dirichlet allocation note -- Prepare
  3. UA OPTI570 量子力学10 位置表象与动量表象
  4. linux命令之less命令
  5. 模块说和神经网络学说_教师招聘中常见的5种脑机能学说
  6. 带有Gluon Ignite和Dagger的JavaFX中的依赖注入
  7. cad二次开发 java_应用Java语言进行AutoCAD2000二次开发.PDF
  8. windbg调试HEAP
  9. 哈工大与北大提出注意力引导的图像去噪
  10. 10 个实验性的 JS/CSS3 编程技术
  11. java file用法_Java File 类的使用方法详解(转)
  12. vscode 显示分支_Git以及vscode里的使用
  13. 用汇编的眼光看C++(之指针2)
  14. LeetCode 78. Subsets
  15. excel 使用连接符合并单元格内容或者给单元格内容添加信息
  16. Trie字典树数组实现
  17. 微型计算机原理实验二,微型计算机原理与接口技术实验指导(第2版)
  18. [SPRD] Q 版本开机 logo 显示原理
  19. V-Rep/CoppeliaSim:Steeringwheel_Tutorial手把手教你制作舵轮底盘
  20. 浅谈数字媒体艺术中的技术应用-1-技术概述

热门文章

  1. Mybatis中<trim>标签用法
  2. Linux使用ubuntu搭建动态路由,实现rip,ospf,路由重分配功能,实例,例子,,从安装环境到代码无比巨巨巨巨巨详细,
  3. Qt富文本 - 插入表格/列表/图片
  4. arcgis gp 选择图层_【干货】ArcGIS的一些常用解决方法
  5. JVM与字节码——2进制流字节码解析
  6. 区域环评项目(Vue3 PC)实现验证码等功能 问题记录
  7. html,css.javascript
  8. excel 如何 筛选,以及筛选后,在复制时 显示 不可对多重选定区域使用此命令的解决办法...
  9. JavaScript学习动画
  10. 解决Axios跨域问题(Axios跨域问题解决方案)