前端高频面试题---计算机网络篇

100 阅读19分钟

1. 什么是Ajax,Ajax都有哪些优点和缺点?

Ajax,全称为“Asynchronous JavaScript and XML”(异步的 JavaScript 和 XML),是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

Ajax的优点主要包括:

  1. 能在不刷新整个页面的情况下与服务器通信维护数据:使用Ajax技术,用户在操作页面时,可以实现不重新加载整个页面的情况下,对数据进行更新和维护。
  2. 前后端分离:这种分离有利于分工合作、减少非技术人员对页面的修改造成的WEB应用程序错误、提高效率、也更加适用于现在的发布系统。
  3. 发送异步请求:使用Ajax技术可以发送异步请求,不妨碍用户进行其他操作。
  4. 局部刷新:使用Ajax技术只需要刷新需要更新的那部分页面,而不是整个页面,能减少用户实际和心理等待时间。
  5. 基于标准化并被广泛支持的技术:Ajax基于标准化并被广泛支持的技术,并且不需要任何插件和下载小程序。

然而,Ajax也存在一些缺点:

  1. 对于手机等移动设备不能很好的支持:这主要是因为手机等移动设备的浏览器和电脑的浏览器存在差异,导致Ajax在移动设备上的兼容性不佳。
  2. 存在安全隐患:例如,黑客可能会利用Ajax的异步请求特性进行攻击。
  3. 违背URL和资源定位的初衷:Ajax的使用可能导致URL的不稳定,违背了URL和资源定位的初衷。
  4. JavaScript的兼容性和Debug都是让人头痛的事:在使用JavaScript做Ajax引擎时,可能会遇到兼容性问题,以及Debug的困难。

2. Ajax的实现流程是怎样的?

Ajax的实现流程可以概括为以下几个步骤:

  1. 创建XMLHttpRequest对象,这是Ajax的核心对象,提供了对HTTP协议的完全访问,包括发送POST和GET请求以及接收服务器的响应。
  2. 使用XMLHttpRequest对象的open()方法与服务端建立连接,指定HTTP请求的方法(如POST、GET等)、携带的数据及验证信息等。
  3. 通过XMLHttpRequest对象的send()方法发送请求给服务器端。
  4. 使用XMLHttpRequest对象提供的onreadystatechange事件监听服务器端的通信状态。当readyState的值改变时,表明服务器已完成通信,可以在该事件的处理函数中处理服务端返回的数据。
  5. 在onreadystatechange事件的处理函数中,通过XMLHttpRequest对象的responseXML或responseText属性获取服务端返回的数据,可以是文本或者一个DOM文档形式的内容。
  6. 将获取到的数据用JavaScript和DOM实现局部刷新,例如用document.getElementById('id').innerText = '...'实现局部刷新,或者用JavaScript将json数据解析后,用window.location.reload()实现整体网页刷新。

以上就是Ajax的实现流程,需要注意的是,Ajax的实现需要服务器逻辑的配合,因此需要后端提供相应的接口来处理Ajax请求和返回数据。

3. 网络请求怎么监控上传/下载,实现进度状况?

要监控网络请求的上传和下载进度,你需要使用一个支持监控网络传输进度的工具或库。在浏览器和Node.js环境中,有不同的方法可以实现这一目标。

在浏览器中,你可以使用XMLHttpRequest或Fetch API来发送请求,并使用ProgressEvent来监控进度。以下是一个使用XMLHttpRequest的示例:

var xhr = new XMLHttpRequest();

xhr.open('GET', 'http://example.com/file', true);
xhr.onprogress = function(event) {
  if (event.lengthComputable) {
    var percentComplete = (event.loaded / event.total) * 100;
    console.log(percentComplete + '% uploaded');
  } else {
    console.log('Unable to compute progress information due to response being incompressible');
  }
};

xhr.send();

在Node.js中,你可以使用httphttps模块,并通过设置http.requesthttps.requeston('progress')事件来监控进度。以下是一个使用http模块的示例:

var http = require('http');

var req = http.request({
  method: 'GET',
  url: 'http://example.com/file',
  on('progress', function(e) {
    if (e.lengthComputable) {
      var percentComplete = (e.loaded / e.total) * 100;
      console.log(percentComplete + '% downloaded');
    } else {
      console.log('Unable to compute progress information due to response being incompressible');
    }
  })
});

req.end();

Axios 是一个基于 Promise 的 HTTP 库,用于浏览器和 Node.js。它提供了监控上传和下载进度的功能,使用 onUploadProgressonDownloadProgress 属性可以获取到上传和下载的进度信息。

下面是一个简单的示例,展示了如何使用 Axios 来监控上传和下载的进度:

  1. 安装 Axios:

如果你还没有安装 Axios,可以通过 npm 来安装:

npm install axios
  1. 使用 Axios 监控上传和下载进度:
const axios = require('axios');

// 上传示例
axios({
  method: 'post',
  url: 'http://example.com/upload',
  data: 'your-file-data', // 这里可以是文件数据或其他数据
  headers: {
    'Content-Type': 'application/octet-stream' // 根据需要设置合适的 Content-Type
  },
  onUploadProgress: function(progressEvent) {
    // 上传进度
    var percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
    console.log(percentCompleted);
  }
}).then(function (response) {
  console.log('文件上传成功!');
}).catch(function (error) {
  console.log('文件上传失败:', error);
});

// 下载示例
axios({
  method: 'get',
  url: 'http://example.com/download',
  responseType: 'stream', // 通过 stream 处理下载数据,比如保存到文件
  onDownloadProgress: function(progressEvent) {
    // 下载进度
    var percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
    console.log(percentCompleted);
  }
}).then(function (response) {
  console.log('文件下载成功!');
}).catch(function (error) {
  console.log('文件下载失败:', error);
});

这个示例展示了如何使用 Axios 的 onUploadProgressonDownloadProgress 属性来获取上传和下载的进度信息。你可以根据实际需求来处理这些进度信息,比如更新 UI 显示进度条等。 这些示例演示了如何使用原生API来监控网络请求的进度。

4. javascript中Ajax解决浏览器缓存问题

在JavaScript中,你可以使用Ajax来解决浏览器缓存问题。浏览器缓存机制对于GET请求会将服务器响应存储起来,以便下次同样的请求到来时直接返回缓存的响应,这有时会导致我们无法获取到最新的数据。

一种常见的解决方式是使用POST请求代替GET请求,因为浏览器不会缓存POST请求的响应。然而,如果你必须使用GET请求(例如,你的URL中包含许多参数),你可以尝试以下方法:

  1. 在URL中添加随机数或时间戳:
var url = 'your_url?rand=' + Math.random();
$.ajax({
    url: url,
    success: function(data) {
        // 处理数据
    }
});

或者使用时间戳:

var url = 'your_url?ts=' + new Date().getTime();
$.ajax({
    url: url,
    success: function(data) {
        // 处理数据
    }
});

每次你发送请求时,由于URL不同,浏览器将不会使用缓存的响应。然而,这种方法可能会对服务器产生很大的压力,因为服务器必须为每个请求生成新的响应。 2. 使用 $.ajaxSetup() 函数来全局设置不使用缓存:

$.ajaxSetup({ cache: false });

此设置会影响后续的所有Ajax请求。但是请注意,这并不能阻止浏览器缓存GET请求的URL,只是在使用缓存的情况下(即相同的URL再次被请求),jQuery会绕过浏览器的缓存直接向服务器发送请求。因此,如果你的应用程序对缓存的需求不大,这种方法是可行的。但是如果你需要对缓存进行更精细的控制,或者如果浏览器缓存对你的应用程序有很大的影响,那么你可能需要使用其他方法。

5. javascript将原生的xhr 封装成 promise

在 JavaScript 中,你可以使用 Promise 对象来封装原生的 XMLHttpRequest(xhr)对象,以便使用更简洁的异步编程方式。下面是一个示例代码,演示如何将原生的 xhr 封装成 Promise:

function fetch(url, options) {
  // 创建一个新的 Promise 对象
  return new Promise(function(resolve, reject) {
    // 创建原生的 XMLHttpRequest 对象
    var xhr = new XMLHttpRequest();

    // 定义请求完成后的回调函数
    xhr.onload = function() {
      if (xhr.status === 200) { // 请求成功
        resolve(xhr.responseText);
      } else { // 请求失败
        reject(new Error(xhr.statusText));
      }
    };

    // 定义请求出错时的回调函数
    xhr.onerror = function() {
      reject(new Error(xhr.statusText));
    };

    // 发送请求
    xhr.open('GET', url, true);
    xhr.send();
  });
}

在这个示例中,fetch 函数接受一个 URL 和一个可选的选项对象作为参数,并返回一个 Promise 对象。在 fetch 函数内部,我们创建一个新的 Promise 对象,并传入一个回调函数作为其参数。这个回调函数包含两个参数:resolverejectresolve 用于在请求成功时将 Promise 对象解析为成功的结果,reject 用于在请求失败时将 Promise 对象拒绝并抛出错误。

接下来,我们创建一个原生的 XMLHttpRequest 对象,并为其定义 onloadonerror 回调函数。当请求完成时,onload 回调函数会被调用,我们检查请求的状态码是否为 200(成功),如果是,则使用 resolve 将 Promise 对象解析为成功的结果;如果不是,则使用 reject 将 Promise 对象拒绝并抛出错误。当请求出错时,onerror 回调函数会被调用,我们使用 reject 将 Promise 对象拒绝并抛出错误。

最后,我们使用 xhr.openxhr.send 方法发送 GET 请求。由于 fetch 函数返回了一个 Promise 对象,我们可以使用 thencatch 方法来处理请求的结果或错误。例如:

fetch('https://api.example.com/data')
  .then(function(response) {
    console.log(response); // 成功时打印响应内容
  })
  .catch(function(error) {
    console.error(error); // 出错时打印错误信息
  });

6. 简单介绍一下HTTP的状态码

HTTP状态码(HTTP status code)是用来表示服务器对客户端请求的响应状态的结果。它们由HTTP协议定义,被广泛应用于互联网的HTTP通信中。以下是常见的HTTP状态码及其意义:

  1. 200 OK:这是最常用的状态码,表示请求成功。客户端发送的请求被服务器理解和处理。
  2. 201 Created:这个状态码表示请求成功,并且服务器已经创建了一个新的资源。
  3. 202 Accepted:服务器已接受请求,但尚未处理。这通常用于表示异步操作,例如发送电子邮件。
  4. 204 No Content:服务器已处理请求,但不需要返回任何内容。这通常用于HEAD请求,或者在更新资源时使用,例如更新缓存。
  5. 301 Moved Permanently:请求的资源已被永久移动到新的URL。这个状态码需要被缓存,以便以后的请求直接转到新的URL。
  6. 302 Found:和301类似,但这是一个临时性的移动。这个状态码不应该被缓存。
  7. 303 See Other:这个状态码表示响应应该在另一个URL上寻找。这个状态码通常与GET请求一起使用。
  8. 304 Not Modified:客户端发送了一个条件性的请求,而服务器没有进行更新,因此返回这个状态码。这个状态码可以节省带宽和减少服务器的负载。
  9. 400 Bad Request:客户端发送了一个格式不正确的请求,或者提供了不完整的参数。
  10. 401 Unauthorized:客户端没有权限访问请求的资源。这通常与身份验证和授权相关。
  11. 403 Forbidden:服务器理解请求客户端的请求,但是拒绝执行。这通常是因为客户端没有权限访问资源。
  12. 404 Not Found:服务器无法找到客户端请求的资源。
  13. 405 Method Not Allowed:客户端请求的方法不被服务器允许。例如,请求一个需要POST方法的URL,但使用了GET方法。
  14. 406 Not Acceptable:服务器无法满足客户端的请求头。
  15. 408 Request Timeout:客户端的请求超时。
  16. 418 I'm a teapot:这个状态码是幽默的,它表示服务器拒绝请求,因为它是一个茶壶。
  17. 500 Internal Server Error:服务器遇到了一个预料之外的情况,无法完成客户端的请求。
  18. 501 Not Implemented:服务器不支持客户端请求的功能。
  19. 502 Bad Gateway:作为网关或代理的服务器尝试执行请求时从上游服务器接收到了无效的响应。
  20. 503 Service Unavailable:服务器暂时无法处理客户端的请求。这可能是由于服务器的维护或者过载。
  21. 504 Gateway Timeout:网关或代理服务器在尝试执行请求时未能从上游服务器(例如,HTTP、FTP、LDAP)或者辅助服务器(例如,DNS)得到及时的响应。
  22. 505 HTTP Version Not Supported:服务器不支持客户端使用的HTTP版本。
  23. 511 Network Authentication Required:客户端需要网络身份验证才能访问资源。这个状态码是为了防止运营商劫持HTTP连接。

7. 同源策略以及跨域

同源策略是一种浏览器安全机制,用于限制一个网页或者一个脚本如何与不同源的资源进行交互。同源指的是协议、域名和端口号都相同,只有在同源的情况下,浏览器才允许网页或者脚本访问对应的资源。同源策略的目的是保护用户的隐私和安全,防止恶意网站通过脚本访问其他网站的敏感信息,例如用户的个人数据、Cookie等。同源策略可以防止这种跨站点攻击。

跨域问题的出现是由于浏览器的同源策略限制。同源策略是浏览器的一种安全机制,服务端之间是不存在跨域的。所谓同源指的是两个页面具有相同的协议、主机和端口,三者有任一不相同即会产生跨域。由于浏览器为了安全考虑,就会产生一个同源政策,不是同一个地方出来的是不允许进行交互的。

解决跨域问题的方法有多种,其中最常见的是JSONP和CORS。JSONP是一种通过动态插入<script>标签来请求跨域数据的方法,它通过在服务器端返回一个JavaScript语句来调用客户端的函数,从而避免了跨域问题。CORS则是在服务器端设置响应头部,添加Access-Control-Allow-Origin字段,以允许来自指定域名的跨域请求。此外,还可以使用代理服务器或者在前端使用Vue等框架来解决跨域问题。

8. fetch发送2次请求的原因?

fetch发送两次请求的原因是因为使用了带预检(Preflighted)的跨域请求。在发送真实的请求之前,浏览器会先发送一个类型为OPTIONS的预检请求。这个预检请求会询问服务器是否允许修改请求头等一些操作,如果服务器支持,才会发送真实的请求。在这个过程中,fetch会发送两次请求:第一次是发送OPTIONS请求,第二次是发送真实的POST请求。

9. 什么是CDN,以及如何优化?

CDN是内容分发网络(Content Delivery Network)的简称,它利用多台网络中转设备,通过中心平台的负载均衡、内容分发、调度等功能模块,根据用户所需要的数据在多级缓存系统中缓存,从而提高用户访问的响应速度、优化带宽使用和保障服务稳定性。

CDN优化的方法包括:

  1. 优化缓存策略:根据服务质量(如就近访问、动态加速、多服务运营)的要求进行数据分发、负载均衡和动态选择最优的网络传输路径,从而达到提高用户访问的响应速度、优化带宽使用和保障服务稳定性的目的。
  2. 优化数据传输路径:CDN善于优化数据传输路径,可以收集节点与周围环境的信息,避免单一节点压力过高,保证每个节点的工作效率,优化用户访问路线,提高数据从源站到客户端的传输速度。且不受运营商相互访问较慢的限制,几乎涵盖所有的线路,可以自动帮助用户选择最快的访问路径。
  3. 健康检查和容错处理:即使某一个节点由于意外发生故障,用户对网站的访问也能自动导向到其他的健康节点上进行响应。

10. HTTP请求方式有几种,分别的使用场景

HTTP请求方式有多种,常见的包括GET、POST、PUT、DELETE、HEAD和OPTIONS。它们的使用场景如下:

  1. GET请求是最常用的请求方式,用于向服务器请求获取某个资源。GET请求的参数会附加在URL的后面,以问号(?)分隔,用于向服务器获取资源,例如查询数据库的数据等。GET请求的特点是请求参数明文传输,请求长度有限制,不适合传输敏感信息。
  2. POST请求用于向服务器提交数据,通常用于表单提交、文件上传等场景。POST请求的参数不会附加在URL的后面,而是包含在请求体中,以二进制形式传输,可以传输大量数据。POST请求的特点是请求参数不可见,请求长度无限制,适合传输敏感信息。
  3. PUT请求用于向服务器更新某个资源,通常用于上传文件、更新数据等场景。PUT请求的参数也包含在请求体中,以二进制形式传输。PUT请求的特点是请求具有幂等性,即重复请求不会对服务器产生影响。
  4. DELETE请求用于向服务器删除某个资源,通常用于删除文件、删除数据等场景。DELETE请求的参数也包含在请求体中,以二进制形式传输。DELETE请求的特点是请求具有幂等性,即重复请求不会对服务器产生影响。
  5. HEAD请求用于向服务器请求获取某个资源的头部信息,通常用于检查资源是否存在、获取资源的元数据等场景。HEAD请求的特点是只返回响应头部信息,不返回响应体,可以减少网络流量和服务器负载。
  6. OPTIONS请求用于向服务器请求获取某个资源所支持的HTTP请求方式,通常用于Web API的开发和调试。OPTIONS请求的特点是只返回支持的请求方式,不返回响应体,可以帮助开发者了解Web API的使用方法。

11. HTTP与HTTPS的区别?

HTTP和HTTPS的主要区别包括以下几点:

  1. 安全性:HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。HTTPS是具有安全性的SSL加密传输协议,需要到ca申请证书,一般免费证书较少,因而需要一定费用。
  2. 连接方式:HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样。HTTP的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
  3. 费用:HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的ssl加密传输协议。HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

综上所述,HTTP和HTTPS的主要区别在于安全性、连接方式以及费用。

12. HTTP2 做了什么优化?

HTTP2主要从以下两个方面进行了优化:

  1. 头部压缩:HTTP2通过HPACK算法对头部进行压缩,减少了传输时间。
  2. 队头阻塞:HTTP2引入了流和帧,解决了HTTP层面上的队头阻塞。

此外,HTTP2还让所有的通信都在一个TCP连接上完成,实现了请求的并发。

13. 解释一下三次握手和四次挥手

三次握手和四次挥手是TCP协议中建立和断开连接的重要步骤。

三次握手:

  1. 第一次握手:客户端发送SYN报文到服务器。这个过程中,客户端发送SYN报文,并在自己已建立连接的传输线上发送(SYN),这时,客户端进入SYN_SEND状态,等待服务器确认。
  2. 第二次握手:服务器收到SYN报文后,需要确认客户的SYN,同时自己也需要发送SYN报文(SYN-ACK)。这个报文是两次握手的一个重要的部分。
  3. 第三次握手:客户端收到服务器的SYN-ACK报文后,会发送一个ACK报文,当服务器收到这个报文后,会进入ESTABLISHED状态,表示成功建立了TCP连接。

四次挥手:

  1. 第一次挥手:当传输完成以后,客户端发送一个FIN报文,表示自己已经没有数据要发送了,要关闭连接了。这时,客户端进入FIN_WAIT_1状态。
  2. 第二次挥手:服务器收到FIN报文后,会发送一个ACK报文,表示我(服务器)收到了你的请求,你(客户端)可以关闭连接了。这时,客户端进入FIN_WAIT_2状态。
  3. 第三次挥手:服务器发送一个FIN报文给客户端,表示服务器自己也没有数据要发送了,也要关闭连接了。这时,服务器进入CLOSE_WAIT状态。
  4. 第四次挥手:客户端收到服务器的FIN报文后,会发送一个ACK报文,表示我(客户端)收到了你的请求,你(服务器)可以关闭连接了。这时,服务器进入TIME_WAIT状态。当2MSL(Maximum Segment Lifetime)时间过去后,这个连接就关闭了。

以上就是三次握手和四次挥手的过程。