py获取前端的参数_前端常见面试 请求篇

博客介绍了XMLHttpRequest的老版本和标准后版本,分析其优点如对原生XHR封装、兼容性好等,缺点有不符合MVVM、异步模型不现代等,还列举了常用API。同时介绍了fetch的特点,如支持PromiseAPI、可拦截请求等,也给出了常用API及实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文转载于 SegmentFault 社区 社区专栏:前端百变机器猫 作者:bilibili

对于前端来说,请求是前端日常工作必备的,通过请求才能与后端进行数据交互,尤其在现在前后端分离的开发模式下,请求显得就更加重要。因此,对于前端开发者来说,掌握请求就很重要。下面将从 http 请求 和常见的几个请求技术做具体的讲解。

No.1

XMLHttpRequest

XMLHttpRequest 一开始只是微软浏览器提供的一个接口,后来各大浏览器纷纷效仿也提供了这个接口,再后来 W3C 对它进行了标准化,按照标准前后可以分为两个版本,具体阐述如下:
版本一(老版本):
//新建一个XMLHttpRequest对象
var xhr=new XMLHttpRequest();

//进行请求
xhr.open('GET', 'url');
xhr.send();

//等待服务器响应
xhr.onreadystatechange = function(){
//该函数会被调用四次,因此需要判断状态是否为4
if ( xhr.readyState == 4 && xhr.status == 200 ) {
alert( xhr.responseText );

} else {

alert( xhr.statusText );

}
};
在老版本中的,对应的具体属性说明如下: 1. xhr.readyState : XMLHttpRequest  对象的状态,等于 4 表示数据已经接收完毕。 2. xhr.status :服务器返回的状态码,等于 200 表示一切正常。 3. xhr.responseText :服务器返回的文本数据 4. xhr.responseXML :服务器返回的  XML 格式 的数据 5. xhr.statusText :服务器返回的状态文本。 老版本因为不是统一的标准,各个浏览器厂商在实现的时候都有一定的差异,而且在存在一些缺陷: 1. 只支持文本数据的传送,无法用来读取和上传二进制文件。 2. 传送和接收数据时,没有进度信息,只能提示有没有完成。 3. 受到"同域限制" (Same Origin Policy) ,只能向同一域名的服务器请求数据。
版本二(标准后的版本):
为了更好的使用 XMLHttpRequest , w3school 发布了标准版本,该版本弥补了版本一的缺陷,也被各大浏览器厂商接受并实现。具体为: 1. 可以设置  HTTP  请求的时限。 2. 可以使用  FormData  对象管理表单数据。 3. 可以上传文件。 4. 可以请求不同域名下的数据 (跨域请求) 。 5. 可以获取服务器端的二进制数据。 6. 可以获得数据传输的进度信息。 当然,一般为了友好的进行兼容各个浏览器,会采用对浏览器进行判断并进行兼容性模式来获取 XMLHttpRequest 的对象。
var xhr;
if (window.XMLHttpRequest) { // Mozilla, Safari...
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
xhr = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
xhr = new ActiveXObject('Microsoft.XMLHTTP'); //IE5,6
} catch (e) {}
}
}
// 请求成功回调函数
xhr.onload = e => {
console.log('request success');
};
// 请求结束
xhr.onloadend = e => {
console.log('request loadend');
};
// 请求出错
xhr.onerror = e => {
console.log('request error');
};
// 请求超时
xhr.ontimeout = e => {
console.log('request timeout');
};
// 请求回调函数.XMLHttpRequest标准又分为Level 1和Level 2,这是Level 1和的回调处理方式
// xhr.onreadystatechange = () => {
// if (xhr.readyState !== 4) {
// return;
// }
// const status = xhr.status;
// if ((status >= 200 && status < 300) || status === 304) {
// console.log('request success');
// } else {
// console.log('request error');
// }
// };

xhr.timeout = 0; // 设置超时时间,0表示永不超时
// 初始化请求
xhr.open('GET/POST/DELETE/...', '/url', true || false);
// 设置期望的返回数据类型 'json' 'text' 'document' ...
xhr.responseType = '';
// 设置请求头
xhr.setRequestHeader('', '');
// 发送请求
xhr.send(null || new FormData || 'a=1&b=2' || 'json字符串');

No.2

ajax 请求

AJAX 是一种与服务器交换数据的技术,可以在不重新载入整个页面的情况下更新网页的一部分,其实就是对 XMLHttpRequest 的封装,可以直接引入 jquery 工具包来进行调用 ajax 请求 (jquery 是一个 js 工具包,其特点是:写得少,做得多) ,具体的 ajax 常用方式如下: ffba92dbcae58b4fbe7c80500c1d4f7e.png 1aa545b48fad242caa58a04766d83fb4.png
优点:
  • 对原生 XHR 的封装
  • 针对 MVC 的编程
  • 完美的兼容性
  • 支持 jsonp
缺点:
  • 不符合 MVVM
  • 异步模型不够现代,不支持链式,代码可读性差
  • 整个 Jquery 太大,引入成本过高
当然,我们可以直接使用 XMLHttpReqeust 来进行实现自己的 ajax 封装,具体代码如下:
const http = {
/**
* js封装ajax请求
* >>使用new XMLHttpRequest 创建请求对象,所以不考虑低端IE浏览器(IE6及以下不支持XMLHttpRequest)
* >>使用es6语法,如果需要在正式环境使用,则可以用babel转换为es5语法 https://babeljs.cn/docs/setup/#installation
* @param settings 请求参数模仿jQuery ajax
* 调用该方法,data参数需要和请求头Content-Type对应
* Content-Type data 描述
* application/x-www-form-urlencoded 'name=哈哈&age=12'或{name:'哈哈',age:12} 查询字符串,用&分割
* application/json name=哈哈&age=12' json字符串
* multipart/form-data new FormData() FormData对象,当为FormData类型,不要手动设置Content-Type
* 注意:请求参数如果包含日期类型.是否能请求成功需要后台接口配合
*/
ajax: (settings = {}) => {
// 初始化请求参数
let _s = Object.assign({
url: '', // string
type: 'GET', // string 'GET' 'POST' 'DELETE'
dataType: 'json', // string 期望的返回数据类型:'json' 'text' 'document' ...
async: true, // boolean true:异步请求 false:同步请求 required
data: null, // any 请求参数,data需要和请求头Content-Type对应
headers: {}, // object 请求头
timeout: 1000, // string 超时时间:0表示不设置超时
beforeSend: (xhr) => {
},
success: (result, status, xhr) => {
},
error: (xhr, status, error) => {
},
complete: (xhr, status) => {
}
}, settings);
// 参数验证
if (!_s.url || !_s.type || !_s.dataType || !_s.async) {
alert('参数有误');
return;
}
// 创建XMLHttpRequest请求对象
let xhr = new XMLHttpRequest();
// 请求开始回调函数
xhr.addEventListener('loadstart', e => {
_s.beforeSend(xhr);
});
// 请求成功回调函数
xhr.addEventListener('load', e => {
const status = xhr.status;
if ((status >= 200 && status < 300) || status === 304) {
let result;
if (xhr.responseType === 'text') {
result = xhr.responseText;
} else if (xhr.responseType === 'document') {
result = xhr.responseXML;
} else {
result = xhr.response;
}
// 注意:状态码200表示请求发送/接受成功,不表示业务处理成功
_s.success(result, status, xhr);
} else {
_s.error(xhr, status, e);
}
});
// 请求结束
xhr.addEventListener('loadend', e => {
_s.complete(xhr, xhr.status);
});
// 请求出错
xhr.addEventListener('error', e => {
_s.error(xhr, xhr.status, e);
});
// 请求超时
xhr.addEventListener('timeout', e => {
_s.error(xhr, 408, e);
});
let useUrlParam = false;
let sType = _s.type.toUpperCase();
// 如果是"简单"请求,则把data参数组装在url上
if (sType === 'GET' || sType === 'DELETE') {
useUrlParam = true;
_s.url += http.getUrlParam(_s.url, _s.data);
}
// 初始化请求
xhr.open(_s.type, _s.url, _s.async);
// 设置期望的返回数据类型
xhr.responseType = _s.dataType;
// 设置请求头
for (const key of Object.keys(_s.headers)) {
xhr.setRequestHeader(key, _s.headers[key]);
}
// 设置超时时间
if (_s.async && _s.timeout) {
xhr.timeout = _s.timeout;
}
// 发送请求.如果是简单请求,请求参数应为null.否则,请求参数类型需要和请求头Content-Type对应
xhr.send(useUrlParam ? null : http.getQueryData(_s.data));
},
// 把参数data转为url查询参数
getUrlParam: (url, data) => {
if (!data) {
return '';
}
let paramsStr = data instanceof Object ? http.getQueryString(data) : data;
return (url.indexOf('?') !== -1) ? paramsStr : '?' + paramsStr;
},
// 获取ajax请求参数
getQueryData: (data) => {
if (!data) {
return null;
}
if (typeof data === 'string') {
return data;
}
if (data instanceof FormData) {
return data;
}
return http.getQueryString(data);
},
// 把对象转为查询字符串
getQueryString: (data) => {
let paramsArr = [];
if (data instanceof Object) {
Object.keys(data).forEach(key => {
let val = data[key];
// todo 参数Date类型需要根据后台api酌情处理
if (val instanceof Date) {
// val = dateFormat(val, 'yyyy-MM-dd hh:mm:ss');
}
paramsArr.push(encodeURIComponent(key) + '=' + encodeURIComponent(val));
});
}
return paramsArr.join('&');
}
}

No.3

vue-resource 请求

vue-resource 是 Vue.js 的一款插件,它可以通过 XMLHttpRequest 或 JSONP 发起请求并处理响应。也就是说, $.ajax 能做的事情, vue-resource 插件一样也能做到,而且 vue-resource 的 API   更为简洁。另外, vue-resource 还提供了非常有用的 inteceptor 功能,使用 inteceptor 可以在请求前和请求后附加一些行为,比如使用 inteceptor 在 ajax 请求时显示 loading 界面。
特点:1. 体积小
vue-resource 非常小巧,在压缩以后只有大约 12KB,服务端启用 gzip 压缩后只有 4.5KB 大小,这远比 jQuery 的体积要小得多。 2. 支持主流的浏览器  
和 Vue.js 一样,vue-resource 除了不支持 IE 9 以下的浏览器,其他主流的浏览器都支持。 3. 支持 Promise API 和 URI Templates  
Promise 是 ES6 的特性,Promise 的中文含义为“先知”,Promise 对象用于异步计算。 
URI Templates 表示 URI 模板,有些类似于 ASP.NET MVC 的路由模板。 4. 支持拦截器  
拦截器是全局的,拦截器可以在请求发送前和发送请求后做一些处理。 
拦截器在一些场景下会非常有用,比如请求发送前在 headers 中设置 access_token,或者在请求失败时,提供共通的处理方式。
常用api
  • get(url, [options])
  • head(url, [options])
  • delete(url, [options])
  • jsonp(url, [options])
  • post(url, [body], [options])
  • put(url, [body], [options])
  • patch(url, [body], [options])
3906b432d9c2ffcfbfcf54f1462d3af7.png
option 详解
366f469ba53f18b70d24251175d9d4e0.png
  

No.4

fetch

1. fetch 是基于 promise 实现的,也可以结合 async/await 2. fetch 请求默认是不带 cookie 的,需要设置 fetch (URL,{credentials:’include’}) 。  3. Credentials 有三种参数: same-origin,include,* 4. 服务器返回 400 500 状态码时并不会 reject ,只有网络出错导致请求不能完成时, fetch 才会被 reject 5. 所有版本的 IE 均不支持原生 Fetch 6. fetch 是 widow 的一个方法
fetch(url).then(function(response) {
return response.json();
}).then(function(data) {
console.log(data);
}).catch(function(e) {
console.log("Oops, error");
});
可配合 es6 的箭头函数进行使用
fetch(url).then(response => response.json())
.then(data => console.log(data))
.catch(e => console.log("Oops, error", e))

No.5

axios

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中
特点:
  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 PromiseAPI
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF
常用 api:
  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.options(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]]
实例:
get 请求
// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});

// 可选地,上面的请求可以这样做
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
post 请求
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
并发请求  
function getUserAccount() {
return axios.get('/user/12345');
}

function getUserPermissions() {
return axios.get('/user/12345/permissions');
}

axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// 两个请求现在都执行完成
}));
拦截器
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
取消请求
var CancelToken = axios.CancelToken;
var source = CancelToken.source();

axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 处理错误
}
});

// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');
当然,无论选择哪一种方式都需要自身结合业务的需要和自我的认知,没有哪个绝对的优秀,也没有哪个绝对不优秀。
- END -
<think>嗯,用户想了解MVC框架相关的面试问题及答案。首先,我需要回忆MVC的基本概念,确保正确解释模型、视图控制器的职责。可能还需要比较MVC其他架构模式,比如MVVM,说明优缺点。然后,用户可能想知道在具体框架中的应用,比如ASP.NET MVC或Spring MVC,如何处理路由、数据绑定等问题。 接下来,用户可能关心实际应用中的问题,比如如何分离关注点,避免代码冗余。需要举例子说明控制器如何处理请求,模型如何与数据库交互,视图如何渲染数据。另外,常见问题可能包括MVC的生命周期,比如在ASP.NET中请求的处理流程。 还要考虑安全性问题,比如在MVC框架中如何防止XSS或CSRF攻击,这可能涉及到数据验证令牌的使用。此外,依赖注在MVC中的应用也是一个高级话题,可以解释如何通过DI实现松耦合。 用户提供的引用中提到了MVC的分层常用框架,需要结合这些信息,确保答案涵盖理论知识实际应用。可能还需要区分不同框架下的MVC实现差异,比如DjangoSpring MVC在处理方式上的不同。 最后,生成的相关问题需要覆盖进阶内容,如MVC的优缺点、与其他模式的对比、具体实现细节优化方法。确保问题能引导读者深理解MVC框架的核心概念实际应用场景。</think>### MVC框架面试常见问题及解答 --- #### **1. 请解释MVC的核心组件及其职责** - **模型(Model)**:管理数据业务逻辑,负责与数据库交互数据验证。例如,用户注册时,模型会处理密码加密存储逻辑[^2]。 - **视图(View)**:负责数据展示,通常由HTML/CSS/模板引擎实现。例如,在电商网站中,商品列表的渲染由视图完成。 - **控制器(Controller)**:接收用户输(如HTTP请求),调用模型处理数据,并选择视图返回响应。例如,用户点击“提交订单”时,控制器调用模型生成订单,并返回确认页面。 $$ \text{MVC工作流程} \approx \text{用户输} \rightarrow \text{控制器} \rightarrow \text{模型} \rightarrow \text{视图} \rightarrow \text{用户} $$ --- #### **2. MVC与三层架构(UI层、业务逻辑层、数据访问层)有何区别?** - **MVC是表现层架构**:仅关注用户交互逻辑,不涉及业务逻辑或数据存储的具体实现。例如,ASP.NET MVC的控制器属于表现层。 - **三层架构是系统分层**:将整个系统划分为UI层(展示)、业务逻辑层(规则处理)、数据访问层(数据库操作)。MVC通常用于实现三层架构中的UI层。 --- #### **3. 如何避免MVC中Controller变得臃肿?** - **策略**: 1. 将业务逻辑抽离到Service层,控制器仅负责协调。 2. 使用中间件或过滤器处理通用逻辑(如权限校验)。 3. 通过依赖注(DI)解耦组件。例如,在Spring MVC中,通过`@Autowired`注服务类。 --- #### **4. 在MVC框架中,如何实现路由(Routing)?** - **原理**:将URL映射到特定的控制器动作方法。例如,在Django中: ```python # urls.py path('articles/<int:year>/', views.article_detail), ``` 对应控制器方法: ```python def article_detail(request, year): # 根据year查询文章 ``` 路由解析过程可表示为: $$ \text{URL} \xrightarrow{\text{路由配置}} \text{Controller.Action(参数)} $$ [^2] --- #### **5. MVC框架如何处理跨站请求伪造(CSRF)攻击?** - **方法**: - 在表单中嵌随机令牌(Token),提交时验证令牌有效性。 - 框架如Django自动生成校验CSRF Token: ```html <form> {% csrf_token %} <input type="text" name="data"> </form> ``` [^4] --- #### **6. MVC的优缺点是什么?** - **优点**: - 职责分离,便于团队协作维护。 - 视图与模型解耦,支持多平展示(如Web、移动端)。 - **缺点**: - 小型项目可能因分层过多导致复杂度上升。 - 控制器可能成为性能瓶颈(需合理设计)。 --- #### **7. 举例说明MVC框架中的数据绑定** - **场景**:用户提交表单更新个人资料。 - **前端(View)**: ```html <input type="text" name="username" value="John"> ``` - **控制器(Controller)**接收请求,自动绑定到模型: ```csharp // ASP.NET MVC public ActionResult UpdateProfile(UserModel user) { // user.username = "John" } ``` - **模型(Model)**验证数据合法性(如用户名长度)[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值