2023高薪前端面试题(二、前端核心——Ajax)

原生Ajax

Ajax简介

  • Ajax全程为Asynchronous JavaScript + XML,就是异步的JS和XML
  • 通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势是:无刷新获取数据,实现局部刷新
  • Ajax是一种用于创建快速动态网页的技术
  • AJAX不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式

Ajax 的应用场景

  1. 页面上拉加载更多数据
  2. 列表数据无刷新分页
  3. 表单项离开焦点数据验证
  4. 搜索框提示文字下拉列表

Ajax的作用、优缺点

作用:ajax用来与后台交互

优点:

  • 最大的优点就是可以实现页面无刷新更新数据,在页面内与服务器通信,提高用户浏览网站应用的体验。
  • 使用异步的方式与服务器通信,不需要中断操作。
  • 可以把以前服务器负担的工作转嫁给客户端,减轻服务器和带宽,可以最大程度减少冗余请求。
  • 基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。

缺点:

  • Ajax干掉了Back和History功能,即对浏览器机制的破坏, 无法使用浏览器前进后退。
  • 安全问题:跨站脚本攻击、SQL注入攻击等。
  • 对搜索引擎的支持比较弱。如果使用不当,AJAX会增大网络数据的流量,从而降低整个系统的性能。

json字符串转换集json对象、json对象转换json字符串

字符串转对象

JSON.parse(json)
eval('(' + jsonstr + ')')  

 对象转字符串

JSON.stringify(json)

 

ajax请求如何取消

(1)原生xhr取消请求

var xhr = new XMLHttpRequest();
xhr.abort();

 ajax常见面试题 - 掘金


  • AJAX的出现与跨域处理

XMLHttpRequest JSON AJAX CORS 四个名词来开会

如何发请求

5种发起请求的方式,主流的、非主流的。

何种方式 请求方法
最常见的form表单 默认GET,多用POST,只此两种 会刷新页面或者新开页面
a 标签 GET请求 也会刷新页面或者新开页面
imgsrc属性 GET 只能以图片的形式展现
link标签 GET 只能以CSSfavicon的形式展现
script标签 GET 只能以脚本的形式运行

可是

  • 我们可能想用GET POST PUT DELETE 方法
  • 不想刷新整个页面,想用一种更易于理解的方式来响应

AJAX出现

浏览器和服务器交互模式 V1.0

AJAX未出现之前,浏览器想从服务器获得资源,注意是获取资源,会经过如下一个过程

  • 浏览器发起请求->服务器接到请求响应给你HTML文档->浏览器收到资源,刷新页面,加载获得的的HTML。简略的过程

交互模式2.0

既然AJAX是一系列的技术的组合体,接下来认识一下其中的几位主角

XMLHttpRequest

XMLHttpRequest对象是用来在浏览器和服务器之间传输数据的。

古代的操作的是:

  1. 浏览器构造XMLHttpRequest实例化对象
  2. 用这个对象发起请求
  3. 服务器响应一个XML格式的字符串,是字符串,是字符串,是字符串,也就是说响应的第四部分是字符串。
  4. JS解析符合XML格式的字符串,更新局部页面。

什么是XML,可扩展标记语言。

XMLHttpRequest实例的详解

正如上面的前端代码片段写的一样,主要用到了open() send()方法, onreadystatechange readyState 属性。

  1. request.open(method, URL, async)方法。

    • 一般用三个参数,第一个参数是请求的方法,可以用GET POST DELETE PUT等等,URL是用访问的路径,async是是否使用同步,默认true,开启异步,不需要做修改即可,所以实际中只写前两个参数
  • 如果非要写false,开启同步,会对浏览器有阻塞效应,而且如果值为false,则send()方法不会返回任何东西,直到接受到了服务器的返回数据
  1. request.send()方法。

    • 发送请求. 如果该请求是异步模式(默认),该方法会立刻返回. 相反,如果请求是同步模式,则直到请求的响应完全接受以后,该方法才会返回
  2. readyState属性。

    • 描述请求的五个状态。

      • 0 === 常量 UNSENT(未打开) open()方法未调用
      • 1 === OPENED (未发送) 只是open()方法调用了
      • 2 === HEADERS_RECEIVED (已获取响应头) send()方法调用了,响应头和响应状态已经返回了
      • 3 === LOADING (正在下载响应体) 响应体下载中,responseText已经获取了部分数据
      • 4 === DONE (请求完成) 整个响应过程完毕了。 这个值是实际中用到的。
      • 只要不等于4,就表示请求还在进行中。
  3. responseText属性是此次响应的文本内容。

  4. onreadystatechange属性。

    • readyState属性的值发生改变,就会触发readyStateChange事件。
    • 我们可以通过onReadyStateChange属性,指定这个事件的回调函数,对不同状态进行不同处理。尤其是当状态变为4的时候,表示通信成功,这时回调函数就可以处理服务器传送回来的数据。即前面的代码片段的处理方式。
  5. 其他的方法、属性、事件详见阮一峰博客、MDN文档


习惯用javaScript的前端是不想和XML打交道的,应该用一种符合js风格的数据格式语言。

JSON

它是一门全新的数据交换语言,不是JavaScript的子集。

  1. JSON很简单,数据类型和JS有点不同的地方。
JavaScript JSON
string "string" 必须写双引号
number number
object {"object": "name"} 必须双引号
undefined 没有
null null
boolean 直接写true false
array array
function 没有
variable
  1. 浏览器的全局对象window上有JSON对象,直接使用window.JSON.parse(string)
let string = request.responseText
let json = window.JSON.parse(string) //string 要符合JSON的格式

以上是JSON解析部分的代码。

此时服务器端代码是

response.statusCode = 200
response.setHeader('Content-Type', 'text/json;charset=utf-8')
response.write(`
    {
      "note" : {
        "to" : "木木",
        "from" : "少少",
        "heading" : "你好哇",
        "content" : "好久不见啊"
      }
    }
`)

CORS

  1. 如果AJAX向非同源的地址发起请求,会报错。
  • 这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200,也就是说即使你看到了200的正确码,也没有用
  1. 但是form表单无视同源政策,可以发起跨域请求。

上述请求响应都没有问题
然而对于AJAX就不行

...
request.open('GET', 'http://www.baidu.com')
...
  • 这是为什么呢,因为

原页面用 form 提交到另一个域名之后,原页面的脚本无法获取新页面中的内容,所以浏览器认为这是安全的。
而 AJAX 是可以读取响应内容的,因此浏览器不能允许你这样做。如果你细心的话你会发现,其实请求已经发送出去了,你只是拿不到响应而已。
所以浏览器这个策略的本质是,一个域名的 JS ,在未经允许的情况下,不得读取另一个域名的内容。但浏览器并不阻止你向另一个域名发送请求。

作者:方应杭
链接:https://www.zhihu.com/question/31592553/answer/190789780
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

那么如何让AJAX跨域发起请求呢。
答案是CORS

  1. CORS目前是W3C的标准,它允许浏览器跨域发起XMLHttpRequest请求,而且可以发起多种请求,不像JSONP只能发起GET请求,全称是"跨域/源资源共享"(Cross-origin resource sharing)。
  • 如果想要发起跨域请求 例如: http://wushao.com:8001 要想访问 http://shaolin.com:8002,可以做如下处理
 request.open('GET', 'http://wushao.com:8001/xxx') //配置request
  • 服务器端的代码需要做如下处理
response.setHeader('Access-Control-Allow-Origin', 'http://shaolin.com:8002')

一定要注意是谁去访问谁,8001去访问8002,那么8001的前端代码要告诉8002的后端代码,咱们是一家人,你和浏览器说说别让它禁我了。

获得请求和响应头

  1. 获得请求头的方法
request.open('GET', 'http://shaolin.com:8002/xxx')// 请求的第一部分
request.setRequestHeader('Content-Type', 'x-www-form-urlencoded')//请求的第二部分
request.setRequestHeader('wushao', '18') //请求的第二部分
request.send('我要设置请求的第四部分') //请求的第四部分
request.send('name=wushao&password=wushao') //请求的第四部分

对应的典型的http请求四部分

GET /xxx HTTP/1.1
HOST: http://shaolin.com:8002
Content-Type: x-www-form-urlencoded
wushao: 18

name=wushao&password=wushao
  1. 获得响应的方法
request.status //响应的第一部分 200
request.statusText //响应的第一部分 OK
request.getAllResponseHeaders //响应的第二部分,这个方法好啊,全部的响应头
request.getResponseHeader('Content-Type') //响应的第二部分具体的
request.responseText //响应的第四部分

 对应的典型的http响应的四部分

HTTP/1.1 200 OK
Content-Type: text/json;charset=utf-8

{
      "note" : {
        "to" : "木木",
        "from" : "少少",
        "heading" : "你好哇",
        "content" : "好久不见啊"
      }
 }

 

回顾一下各个status对应的意思

100
200 === OK,请求成功
301 === 被请求的资源已永久移动到新位置
302 === 请求临时重定向,要求客户端执行临时重定向
304 === 和上次请求一样,未改变
403 === 服务器已经理解请求,但是拒绝访问
404 === 请求失败,服务器上没有这个资源
502 === 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
503 === Service Unavailable 由于临时的服务器维护或者过载,服务器当前无法处理请求。

转载自: 

AJAX的出现与跨域处理 - 简书


  • 手写Ajax原始请求

AJAX 创建异步对象 XMLHttpRequest
Ajax 能够在不重新加载整个页面的情况下与服务器交换数据并更新部分网页内容,实现局部刷新,大大降低了资源的浪费,是一门用于快速创建动态网页的技术,ajax 的使用分为四部分:
1、创建 XMLHttpRequest 对象 var xhr = new XMLHttpRequest();
2、向服务器发送请求,使用 xmlHttpRequest 对象的 open send 方法,
3、监听状态变化,执行相应回调函数, 每当 readyState 改变时,onreadystatechange 函数就会被执行。
4、读取响应数据,可以通过 responseText 属性来取回由服务器返回的数据。
//1.创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest();
//2.规定请求的类型、URL 以及是否异步处理请求。
xhr.open('GET',url,true); //默认true,开启异步,不需要做修改即可,所以实际中只写前两个参数
//3.发送信息至服务器时内容编码类型
//设置响应头
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
//4.发送请求
xhr.send(null);  
//5.接受服务器响应数据
xhr.onreadystatechange = function () {
    if(xhr.readyState ===4){
    //判断响应状态码  200 404 403 401 500
    //2xx 成功
      if(xhr.status >= 200 && xhr.status < 300){
            console.log(xhr.responseText);
      }else{
     
      }
   }
}

区别描述

onload事件

onreadystatechange事件

是否兼容IE低版本

不兼容

兼容

是否需要判断Ajax状态码

不需要

需要

被调用次数

一次

多次


将原生的 ajax 封装成 promise

var myNewAjax = function (url) {
        return new Promise(function (resolve, reject) {
            var xhr = new XMLHttpRequest(); //创建Ajax对象
            xhr.open('get', url, true); //告诉浏览器以什么方式发送请求  以及请求发送到哪
            xhr.send(data); //发送请求
            xhr.onreadystatechange = function () { //设置响应服务器端数据处理
                if (xhr.status == 200 && readyState == 4) {
                    var json = JSON.parse(xhr.responseText);
                    resolve(json)
                }
                else if(xhr.readyState == 4 && xhr.status != 200)
                {
                    reject('error');
                }
            }
        })
    }

readyState==4是什么意思?

1、在ajax中有状态码readyState,readyState是XMLHttpRequest对象的一个属性,用来标识当前XMLHttpRequest对象处于什么状态。

readyState总共有5个状态值,分别为0~4,每个值代表了不同的含义

0:未初始化,XMLHttpRequest对象还没有完成初始化

1:载入,XMLHttpRequest对象开始发送请求

2:载入完成,XMLHttpRequest对象的请求发送完成

3:解析,XMLHttpRequest对象开始读取服务器的响应

4:完成,XMLHttpRequest对象读取服务器响应结束

所以说readyState == 4表示已经完成了ajax请求。

2、open函数最后一个参数设置为布尔值true表示向服务器发送的请求是异步的。也就说代码执行send方法后,不会在此处一直等待服务器执行的结果,而是继续往后执行后面的代码。


ajax 状态码

参考回答:
xhr.readyState // 获取Ajax状态码

0 - (未初始化)还没有调用 send()方法

1 - (载入)已调用 send()方法,正在发送请求

2 - (载入完成)send()方法执行完成,已经接收到全部响应内容
3 - (交互)正在解析响应内容
4 - (完成)响应内容解析完成,可以在客户端调用了

对比题

1.Ajax、Fetch、Axios三者的区别?

  • ajax是js异步技术的术语,早起相关的api是xhr,它是一个术语
  • fetch是es6新增的用于网络请求标准api,它是一个api
  • axios是用于网络请求的第三方库,它是一个库

  • Ajax有几种请求方式?它们的优缺点?

常用的post,get,delete。不常用copy、head、link等等。

a.代码上的区别

(1)get通过url传递参数
(2)post设置请求头 规定请求数据类型

b.使用上的区别

(1)post比get安全 ,(因为post参数在请求体中。get参数在url上面)
(2)get传输速度比post快 根据传参决定的。(post通过请求体传参,后台通过数据流接收。速度稍微慢一些。而get通过url传参可以直接获取)
(3)post传输文件大理论没有限制, get传输文件小大概7-8k ie4k左右;

(4)get获取数据 post上传数据,(上传的数据比较多 而且上传数据都是重要数据。所以不论在安全性还是数据量级 post是最好的选择)。


• GET 和 POST 的区别

参考回答:

  1. get 参数通过 url 传递,post 放在 request body 中。
  2. get 请求在 url 中传递的参数是有长度限制的,而 post 没有。
  3. get 比 post 更不安全,因为参数直接暴露在 url 中,所以不能用来传递敏感信息。
  4. get 请求只能进行 url 编码,而 post 支持多种编码方式 get 请求会浏览器主动 cache,而post 支持多种编码方式。
  5. get 请求参数会被完整保留在浏览历史记录里,而 post 中的参数不会被保留。
  6. GET 和 POST 本质上就是 TCP 链接,并无差别。但是由于 HTTP 的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。GET 和 POST 的底层也是 TCP/IP,GET/POST 都是 TCP 链接。
  7. GET 产生一个 TCP 数据包;POST 产生两个 TCP 数据包。对于 GET 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务器响应200(返回数据);而对于 POST,浏览器先发送 header,服务器响应 100 continue,浏览器再发送data,服务器响应 200 ok(返回数据)。

一、功能不同

1、get是从服务器上获取数据。GET - 从指定的资源请求数据。

2、post是向服务器传送数据。POST - 向指定的资源提交要被处理的数据。

二、过程不同

1、get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。

2、post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。

三、获取值不同

1、对于get方式,服务器端用Request.QueryString获取变量的值。

2、对于post方式,服务器端用Request.Form获取提交的数据。

四、传送数据量不同

1、get传送的数据量较小,不能大于2KB。

2、post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。


  • 假如我有多个请求,我需要让这些 ajax 请求按照某种顺序一次执行,有什么办法呢?

递归+promise:

//按顺序执行多个ajax命令,因为数量不定,所以采用递归
function send(action, arg2) {
//将多个命令按顺序封装成数组对象,递归执行
//利用了deferred对象控制回调函数的特点
    $.when(send_action(action[0], arg2))
    .done(function () {
//前一个ajax回调函数完毕之后判断队列长度
if (action.length > 1) {
//队列长度大于1,则弹出第一个,继续递归执行该队列

    action.shift();
    send(action, arg2);
    }
    }).fail(function (){
    //队列中元素请求失败后的逻辑
    //重试发送
    //send(action, arg2);
    //忽略错误进行下个
    //if (action.length > 1) {
    //队列长度大于1,则弹出第一个,继续递归执行该队列
        //    action.shift();
        //    send(action, arg2);
        //}
        });
        }
    //处理每个命令的ajax请求以及回调函数

function send_action(command, arg2) {
var dtd = $.Deferred();//定义deferred对象

    $.post(
    "url",
    {
    command: command,
    arg2: arg2
    }
    ).done(function (json) {
    json = $.parseJSON(json);

//每次请求回调函数的处理逻辑

    //
    //
    //
//逻辑结束
dtd.resolve();
}).fail(function (){
//ajax请求失败的逻辑
dtd.reject();
});
return dtd.promise();//返回Deferred对象的promise,防止在外部修改状态

}

工作中有时间碰到多个ajax请求,需要按照顺序进行数据请求且保证数据是按照请求的顺序有序返回。所以需要对请求进行包装处理。 jquery自带的case when方式仅能保证请求是按顺序发出的,但不能保证请求的数据按顺序返回。

具体处理方式如下:

1、创建一个存放ajax请求的数组,

2、创建一个执行ajax请求的函数,在函数内执行数组中第一个ajax函数,在请求返回后将该ajax函数删除,然后判断数组的长度,若数组长度大于零,表示还有请求没有完成,继续执行该ajax函数。实际上是利用递归原理来处理。

例:

var categorieList = [  
        {  
            categorieId: 1,  
            id: 11151, //测试用  
            type: "技术"  
        },{  
            categorieId: 2,  
            id: 11164, //测试用  
            type: "能力"  
        },{  
            categorieId: 3,  
            id: 11146, //测试用  
            type: "产品"  
        }  
    ];  
    if( typeof(result.label) != "undefined" && !isBlank(result.label) ){  
        var ajaxes = []; //用于存储参数对象的队列  
        for(var i=0; i< categorieList.length; i++){  
            ajaxes.push({
                categorieId: categorieList[i].categorieId, 
                type: categorieList[i].type, 
                result: result 
            });  
        }  

   创建执行ajax请求的函数:

var  executeAjax = function(){  
	if(ajaxes.length < 1){  
		return;  
	}  
	var params = ajaxes[0];  
	$.ajax({  
		 type:  .....  
		 success: function(response){  
			   ...  
			ajaxes.shift();   //删除队列中的第一个请求  
			if( ajaxes.length > 0){ //如果队列中还有请求,就接着递归执行executeAjax函数,直到队列为空
				executeAjax();  
			}  
		 }  
	});  
};  
executeAjax(); //执行函数请求。  

多ajax请求顺序执行 - 一路前行 - ITeye博客

​​​​​​​

你可能感兴趣的:(2023高薪前端面试题(二、前端核心——Ajax))