您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

jQuery Ajax

相信很多有一定前端经验的同学肯定听说过 jQuery,并且稍有研究的人肯定也知道 jQuery 提供了 Ajax 系列的工具。

事实上,市面上有各种各样的 Ajax 类库可以供我们使用,它们更加健壮、更加成熟、并且设计也更为合理。在我们在实际开发的过程中,我们并不直接使用 XMLHttpRequest,而是会使用这些封装好的经得起考验的类库,来为我们的程序提供服务,让我们的开发者更加专注在本身的业务上。

那么,本章节挑选了曾经盛极一时的 jQuery 的工具 Ajax 来做展开介绍。

首先,我先引用 jQuery 的设计宗旨:

Write less, do more.

稍有研究的同学都知道 jQuery 非常好用,这些都得益于 jQuery 优秀的设计思想。它不但能够提供便捷的元素选择及操作方式,还提供了一系列的工具、链式操作等等,使得我们在开发过程中变得足够简易。Ajax 同样继承了 jQuery 的优秀设计思想,提供了更为人性化的接口和配置。接下来我们来聊聊 jQuery Ajax :

因为我们使用的 Ajax 是 jQuery 提供的,因此我们需要在中引入 jQuery 脚本。

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>

Tips: 注意 jQuery 脚本要放在使用到 jQuery 的脚本之前,这样才可以在我们的中愉快的玩耍~

load(url, [data], [callback])

load 是 jQuery 非常便捷的 Ajax 交互,从上看,load 接受三个参数,分别是 url,发送的参数以及响应结果的回调。实际上,后两个参数我们也常常可以忽略。

我们先来看简单的例子:

假设我们要在中插入从后端请求回来的数据,那么我们会怎么做?

有同学非常聪明,可能会说:我先启用 ajax ,发送 GET 请求,在成功的时候回调里面再操作的元素对象,为 innerHTML 赋值结果。

是的,基本流程就是之后再操作元素数据即可。但是,jQuery 的 load 可能更加简单哦。不信请看:

router.get("/jquery_ajax/load", function(req, res) {
    res.send('<p>返回的</p>');
});
<div id="container"></div>
$('#container').load('/jquery_ajax/load')

怎么样,只需要一行,我们就可以往目标元素中数据了。这确实是非常的方便!

事实上, load 属于基于 $.ajax 再次封装的简易的 API 。有兴趣的同学可以去扣一下源码来看看。大概实现就是这样:

jQuery.fn.load = function( url, params, callback ) {
    var selector, type, response,
        self = this,
        off = url.indexOf( " " );

   // xxx

    // If we have elements to modify, make the request
    if ( self.length >  ) {
        jQuery.ajax( {
            // xxx
        } ).done( function( responseText ) {
            // xxx
        } ).always( callback && function( jqXHR, status ) {
            // xxx
        } );
    }
    return this;
};

这里我隐去了一些具体实现,目的只是为了说明 load 内部的基本实现是怎么样的即可。对具体实现有兴趣的同学可以自行读一下源。

事实上,load 的定制化相对较高,必定无法满足更为灵活的需求。因此,我们多数时候会使用 jQuery 封装好的更为底层的 API —— $.ajax

jQuery.ajax(url,[settings])

如上所示,$.ajax 接受两个参数,分别为 url 和 配置对象。其中:

在配置对象中,我们通常会传入我们希望指定的配置项,来指定我们的 Ajax 的行为和。当然有些参数我们并不一定要去指定,因为有的配置项本身会有认配置,只要该认配置符合你的使用需求即可。有兴趣的同学也可以到 详细查看每个配置项的认值以及含义。

常用的配置项我们简单带过,比如:

$.ajax 提供了非常人性化的配置项,分别有:beforeSend、error、dataFilter、success、complete。我把它们分别归为请求前和请求后两个阶段。

对于 Ajax 的请求来说,我们在正式发送请求之前可能会对我们的 Ajax 做一些提前的配置或者预先要进行的操作。那么,我们可以非常愉快的使用 beforeSend 。

beforeSend(xhr)

beforeSend 指定的是发送请求之前要先执行的。 并且,jQuery 会在 beforeSend 中传入当前的 XMLHttpRequest 对象,方便我们在该中做预先的操作。打个比方,我们可以通过这个,给当前的 Ajax 请求的 headers 项。

当我们成功的发送了请求,那么我们接下来就是要返回结果的问题了。

在服务器成功响应之后,我们需要对结果进行和处理,这个时候 dataFilter 和 success 就派上用场了。其中:

dataFilter :

dataFilter (Object data, String type)

dataFilter 接受服务端返回的原始数据和 dataType 值作为参数,会在请求成功之后,目的是为了我们可以在请求成功之后对数据进行进一步的处理、过滤。 对比另外 —— success。

success

success(( Object data, String textStatus, jqXHR jqXHR ))

success 是成功响应的,优先级在 dataFilter 之后。 它接受三个参数,分别是:数据对象、状态描述字符串以及 XHR 对象。我们通常会个里面进行对结果的操作。

当然也会有请求失败的情况,那么我们该如何来处理呢?

$.ajax 同样提供了人性化的回调 error 。

error(jqXHR jqXHR, String textStatus, String errorThrown)

error 接受三个参数,分别为 XHR 对象、状态描述字符串以及捕获异常的字符串。假如我在程序中定义了这样 $.ajax :

$.ajax({
    url: '/jquery_ajax/get/2',
    method: 'GET',
    error (xhr, status, err) {
        console.log(xhr, status, err)
    }
})

其中,我们的 url 指定的是不存在的接口,那么我们可以在控制台看到这样的打印信息:

显而易见,我们可以很轻易个中到请求的信息。事实上,我们常常会在 error 中对异常做进一步的操作。举个栗子,在我们开发的应用中,我们不可能把请求失败的这样结果自己在程序中抹干净不上报给知道,如果我们内部自己消化了,不知道自己到底成不成功,这样的体验就非常糟糕了!这个时候,我们或许会选择弹框,告知我们失败的结果以及下一步的操作。

好了,来继续思考这样场景:假如我们发起 $.ajax(),为了让感知,我们一般会弹起 loading 的界面,让稍微等待一下。那问题来了,我们的 loading 界面到底什么时候应该呢?是在请求成功之后吗?那如果请求发生怎么办?总不能了就不 loading 了吧?那或者在成功和失败的回调中都执行 loading 的,这貌似是不错的做法,但是这样的做法我们要在两个地方都进行改动,未免太过麻烦,并且后期也不好维护呢。

别忘了,我们还有 complete

complete(jqXHR jqXHR, String textStatus)

complete 会在请求完成之,无论请求成功或者失败。 我们可以很好地将请求的善后工作交给它来进行。

在 jQuery 中,通常都会有一些耗时比较长的操作,我们是无法马上得到结果的。对于 $.ajax 而言,我们的请求往往都要依靠网络传输和服务端的处理。这时我们的一贯处理方式就是给定某个回调,当耗时操作结束返回数据以后,及时这个回调来进行进一步的处理。

在 jQuery 1.5 版本之后就改变了这一点,deffered 在 jQuery 中诞生了!

字面来看,defer 代表的是“延迟”的意思,这也对应着我们的延时操作。使用 deffered ,我们将改变使用回调的做法,转而使用的是链式。这其实也正是拥抱了 jQuery 的设计思想,使用过 jQuery 的同学都知道,jQuery 对节点的操作往往都会封装为 jQuery 的对象进行,而 deffered 也正是如此,会对延时操作做统一的管理,并且提供统一的编程接口,比如 done 和 fail

举个栗子,我们使用 $.ajax 来进行数据的请求,可以变体为:

$.ajax({
    url: '/jquery_ajax/get',
    method: 'GET',
    data: {
        a: '123',
        b: '234'
    }
}).done(data => {
    console.log(data)
}).fail(err => {
    console.log(err)
})

事实上在 deffered 出来之后,$.ajax 也开始返回 deffered 对象。细心的同学可以看到,这不是 promise 么?是的,可以这样说,但是也不尽然,jQuery 根据自己的需要实现了这样东西,它 promise 的一些规范,同时也自己的特权。我们在使用 deffered 的时候,很直观的可以看到,我们从回调的传统方式中解脱了出来。除此之外,由于 Promise 的反控制反转,使得我们的程序变得更加健壮,我们对结果操作更有掌控权。


联系我
置顶