ajax原理及常见面试题

引语

AJAXAsynchronous Javascript And XML(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。

AJAX是一种用于创建快速动态网页的技术。它可以令开发者只向服务器获取数据(而不是图片,HTML文档等资源),互联网资源的传输变得前所未有的轻量级和纯粹,这激发了广大开发者的创造力,使各式各样功能强大的网络站点,和互联网应用如雨后春笋一般冒出,不断带给人惊喜。

一、什么是AJAX

Ajax是一种异步请求数据的web开发技术,对于改善用户的体验和页面性能很有帮助。简单地说,在不需要重新刷新页面的情况下,Ajax 通过异步请求加载后台数据,并在网页上呈现出来。常见运用场景有表单验证是否登入成功、百度搜索下拉框提示和快递单号查询等等。

Ajax的目的是提高用户体验,较少网络数据的传输量。同时,由于AJAX请求获取的是数据而不是HTML文档,因此它也节省了网络带宽,让互联网用户的网络冲浪体验变得更加顺畅。

二、AJAX原理是什么

Ajax相当于在用户和服务器之间加了一个中间层,使用户操作与服务器响应异步化。并不是所有的用户请求都提交给服务器,像一些数据验证和数据处理等都交给Ajax引擎自己来做,只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。

Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发送异步请求,从服务器获得数据,然后用JavaScript来操作DOM而更新页面。这其中最关键的一步就是从服务器获得请求数据。要清楚这个过程和原理,我们必须对 XMLHttpRequest有所了解。

XMLHttpRequest是ajax的核心机制,它是在IE5中首先引入的,是一种支持异步请求的技术。简单的说,也就是JavaScript可以及时向服务器提出请求和处理响应,而不阻塞用户。达到无刷新的效果。

三、AJAX的使用

1. 创建Ajax核心对象XMLHttpRequest(记得考虑兼容性)

let xhr = null;
if (window.`XMLHttpRequest`) {// 兼容 IE7+, Firefox, Chrome, Opera, Safari  
    xhr = new `XMLHttpRequest`();  
} else {// 兼容 IE6, IE5 
    xhr = new ActiveXObject("Microsoft.XMLHTTP");  
} 

2. 向服务器发送请求

xhr.open(method, url, async);  
send(string);//`POST`请求时才使用字符串参数,否则不用带参数。
  • method:请求的类型;GETPOST
  • url:文件在服务器上的位置
  • async:true(异步)或 false(同步)

注意:POST请求一定要设置请求头的格式内容

xhr.open("`POST`", "test.html", true);  
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");  
xhr.send("fname=Henry&lname=Ford");  //`POST`请求参数放在send里面,即请求体

一个Promise对象实现的 Ajax 操作的例子:

const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();
  });
  return promise;
};

getJSON("/posts.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error('出错了', error);
});

3. 服务器响应处理(区分同步跟异步两种情况)

responseText获得字符串形式的响应数据。 responseXML获得XML 形式的响应数据。

同步处理
xhr.open("`GET`","info.txt",false);  
xhr.send();  
document.`GET`ElementById("myDiv").innerHTML = xhr.responseText; //获取数据直接显示在页面上
异步处理(推荐)

相对来说比较复杂,要在请求状态改变事件中处理。

xhr.onreadystatechange = function() { 
    if (xhr.readyState == 4 && xhr.status == 200){    
    document.`GET`ElementById("myDiv").innerHTML = xhr.responseText;  
    }
} 
什么是readyState

readyStateXMLHttpRequest对象的一个属性,用来标识当前XMLHttpRequest对象处于什么状态。 readyState总共有5个状态值,分别为0~4,每个值代表了不同的含义:

  • 0:未初始化 — 尚未调用.open()方法;
  • 1:启动 — 已经调用.open()方法,但尚未调用.send()方法;
  • 2:发送 — 已经调用.send()方法,但尚未接收到响应;
  • 3:接收 — 已经接收到部分响应数据;
  • 4:完成 — 已经接收到全部响应数据,而且已经可以在客户端使用了;
什么是status?

HTTP状态码(status)由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:

  • 1xx(临时响应):表示临时响应并需要请求者继续执行操作的状态码。
  • 2xx(成功):表示成功处理了请求的状态码。
  • 3xx(重定向):表示要完成请求,需要进一步操作。通常,这些状态代码用来重定向。
  • 4xx(请求错误):这些状态码表示请求可能出错,妨碍了服务器的处理。
  • 5xx(服务器错误):这些状态码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错。
常见的状态码

仅记录在 RFC2616 上的 HTTP 状态码就达 40 种,若再加上 WebDAV(RFC4918、5842)和附加 HTTP 状态码 (RFC6585)等扩展,数量就达 60 余种。接下来,我们就介绍一下这些具有代表性的一些状态码。

  • 200表示从客户端发来的请求在服务器端被正常处理了。
  • 204表示请求处理成功,但没有资源返回。
  • 301表示永久性重定向。该状态码表示请求的资源已被分配了新的URI,以后应使用资源现在所指的URI。
  • 302表示临时性重定向。
  • 304表示客户端发送附带条件的请求时(指采用GET方法的请求报文中包含if-matched,if-modified-since,if-none-match,if-range,if-unmodified-since任一个首部)服务器端允许请求访问资源,但因发生请求未满足条件的情况后,直接返回304Modified(服务器端资源未改变,可直接使用客户端未过期的缓存)
  • 400表示请求报文中存在语法错误。当错误发生时,需修改请求的内容后再次发送请求。
  • 401表示未授权(Unauthorized),当前请求需要用户验证
  • 403表示对请求资源的访问被服务器拒绝了
  • 404表示服务器上无法找到请求的资源。除此之外,也可以在服务器端拒绝请求且不想说明理由时使用。
  • 500表示服务器端在执行请求时发生了错误。也有可能是Web应用存在的bug或某些临时的故障。
  • 503表示服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。

4. GETPOST请求数据区别

  1. GET在浏览器回退时是无害的,而POST会再次提交请求。
  2. GET产生的URL地址可以被Bookmark,而POST不可以。
  3. GET请求会被浏览器主动cache,而POST不会,除非手动设置。
  4. GET请求只能进行url编码,而POST支持多种编码方式。
  5. GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  6. GET请求在URL中传送的参数是有长度限制的,而POST么有。
  7. 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
  8. GETPOST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  9. GET参数通过URL传递,POST放在Request body中。

GETPOST使用场景:若符合下列任一情况,则推荐用POST方法:

  • 请求的结果有持续性的副作用,例如,数据库内添加新的数据行。
  • 若使用GET方法,则表单上收集的数据可能让URL过长。
  • 要传送的数据不是采用7位的ASCII编码。

若符合下列任一情况,则推荐用GET方法:

  • 请求是为了查找资源,HTML表单数据仅用来帮助搜索。
  • 请求结果无持续性的副作用。
  • 收集的数据及HTML表单内的输入字段名称的总长不超过1024个字符。

四、常见AJAX面试题

什么是AJAX?AJAX作用是什么?

详见本文内容=>

原生JavaScript AJAX请求有几个步骤?分别是什么?
//创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest();
//发送信息至服务器时内容编码类型
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
//接受服务器响应数据
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && (xhr.status == 200) { 
        // let data = xhr.responseText;  
    }
};
//规定请求的类型、URL 以及是否异步处理请求。
xhr.open('GET',url,true);
//发送请求
xhr.send(null);  
JSON字符串和JSON对象的相互转换
//字符串转对象
JSON.parse(json)
eval('(' + jsonstr + ')')   

// 对象转字符串
JSON.stringify(json)
AJAX几种请求方式?他们的优缺点?

详见本文内容=>

HTTP常见状态码有哪些?

详见本文内容=>

什么情况造成跨域(什么是同源策略)?

同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以xyz.com下的js脚本采用Ajax读取abc.com里面的文件数据是会被拒绝的。

同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

举个例子:

不受同源策略限制的情况:

  1. 页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
  2. 跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的,,,
跨域解决方案有哪些?
  • JSONP 只能解决GET跨域(问的最多) 原理:动态创建一个script标签。利用script标签的src属性不受同源策略限制。因为所有的src属性和href属性都不受同源策略限制。可以请求第三方服务器数据内容。 步骤:

    1\. 创建一个script标签
    2\. script的src属性设置接口地址
    3\. 接口参数,必须要带一个自定义函数名 要不然后台无法返回数据。
    4\. 通过定义函数名去接收后台返回数据
    
    ```js
    //去创建一个script标签
    let script = document.createElement("script");
    //script的src属性设置接口地址 并带一个callback回调函数名称
    script.src = "http://127.0.0.1:8888/index.php?callback=jsonpCallback";
    //插入到页面
    document.head.appendChild(script);
    //通过定义函数名去接收后台返回数据
    function jsonpCallback(data){
        //注意:jsonp返回的数据是json对象可以直接使用
        //ajax 取得数据是json字符串需要转换成json对象才可以使用。
    }
  • CORS:跨域资源共享 原理:服务器设置Access-Control-Allow-OriginHTTP响应头之后,浏览器将会允许跨域请求限制:浏览器需要支持HTML5,可以支持POSTPUT等方法兼容ie9以上需要后台设置

    Access-Control-Allow-Origin: *              //允许所有域名访问,或者
    Access-Control-Allow-Origin: http://a.com   //只允许所有域名访问
  • 设置 document.domain原理:相同主域名不同子域名下的页面,可以设置document.domain让它们同域限制:同域document提供的是页面间的互操作,需要载入iframe页面

    // URL http://a.com/foo
    var ifr = document.createElement('iframe');
    ifr.src = 'http://b.a.com/bar'; 
    ifr.onload = function(){
        var ifrdoc = ifr.contentDocument || ifr.contentWindow.document;
        ifrdoc.getElementsById("foo").innerHTML);
    };
    ifr.style.display = 'none';
    document.body.appendChild(ifr);
  • ES5 postMessageES5新增的 postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递. 语法:

    postMessage(data,origin)
  • 用Apache做转发(逆向代理),让跨域变成同域

五、结语

其实通过 XMLHttpRequest或者封装后的框架进行网络请求,这种方式已经有点老旧了,配置和调用方式非常混乱,近几年刚刚出来的Fetch提供了一个更好的替代方法,它不仅提供了一种简单,合乎逻辑的方式来跨网络异步获取资源,而且可以很容易地被其他技术使用。


推荐阅读:【专题:JavaScript进阶之路】ES6 PromiseJavaScript之函数柯理化ES6 尾调用和尾递归Git常用命令小结浅谈 MVC 和 MVVM 模型

参考Ajax原理一篇就够了 · Issue #45 · ljianshu/Blog · GitHubAjax 简介再也不学AJAX了!(一)AJAX概述HTTP菜鸟教程Ajax MDN文档ajax常见的面试问题 - 斧子兔 - 博客园


我是Cloudy,现居上海,年轻的前端攻城狮一枚,爱专研,爱技术,爱分享。个人笔记,整理不易,感谢关注阅读点赞收藏文章有任何问题欢迎大家指出,也欢迎大家一起交流各种前端问题!

原文链接:segmentfault.com

上一篇:重温Javascript:数据类型
下一篇:AJAX原理及常见面试题

相关推荐

  • 🚩四年前端带你理解路由懒加载的原理

    前言 说起路由懒加载,大家很快就知道怎么实现它,但是问到路由懒加载的原理,怕有一部分小伙伴是一头雾水了吧。下面带大家一起去理解路由懒加载的原理。 路由懒加载也可以叫做路由组件懒加载,最常用的是通过im...

    1 个月前
  • 🔥 Promise|async|Generator 实现&原理大解析 | 9k字

    笔者刚接触async/await时,就被其暂停执行的特性吸引了,心想在没有原生API支持的情况下,await居然能挂起当前方法,实现暂停执行,我感到十分好奇。好奇心驱使我一层一层剥开有关JS异步编程的...

    3 个月前
  • (立下flag)每日10道前端面试题-15 关于【高级技巧】十问

    (/public/upload/4dc64bf14f4bd714fcd87e98b6a10373) 第一问:安全类型检测——typeof和instanceof 区别以及缺陷,以及解决方案 这两...

    2 个月前
  • (ajax)query中全局事件ajaxStart ajaxStop

    Jquery中当一个Ajax请求启动时,并且没有其他未完成的Ajax请求时, 将调用ajaxStart()方法。 同样,ajaxStop()方法则是在所有Ajax请求都完成时调用。

    1 年前
  • 高级前端面试题大汇总(只有试题,没有答案)

    面试题来源于网络,看一下高级前端的面试题,可以知道自己和高级前端的差距。有些面试题会重复。 ...

    2 年前
  • 面试题|手写JSON解析器

    这周的 Cassidoo 的每周简讯有这么一个面试题:: 写一个函数,这个函数接收一个正确的 JSON 字符串并将其转化为一个对象(或字典,映射等,这取决于你选择的语言)。

    4 个月前
  • 面试题:没有es6老项目,如何用jq解决异步的问题?

    我们都知道es6提供了promise异步写法,但是大部分的公司都是jq写的,那我们如何用Jq来写和promise异步一样的写法呢?这个知道的人不多下面我们就来写写把 注意: 1 JQ 1.5以上 ...

    2 年前
  • 面试题:nginx有配置过吗?反向代理知道吗?

    这篇文章主要是针对跨域进行配置,如果大佬们会配置的话,就不用看了~简述反向代理和正向代理反向代理: 我们将请求发送到服务器,然后服务器对我们的请求进行转发,我们只需要和代理服务器进行通信就好,偷个图:...

    2 个月前
  • 面试题:Hooks 与 React 生命周期的关系

    React 生命周期很多人都了解,但通常我们所了解的都是 单个组件 的生命周期,但针对 Hooks 组件、多个关联组件(父子组件和兄弟组件) 的生命周期又是怎么样的喃?你有思考和了解过吗,接下来我们将...

    1 年前
  • 面试题(前端-字节跳动)

    只是做个记录 第一题 我叫王大锤,是一家出版社的编辑。我负责校对投稿来的英文稿件,这份工作非常烦人,因为每天都要去修正无数的拼写错误。但是,优秀的人总能在平凡的工作中发现真理。

    10 个月前

官方社区

扫码加入 JavaScript 社区