使用AJAX技术发送异步请求
在传统的Web应用中,程序的操作都是基于请求响应循环来实现
的。
故每当页面状态需要变动,或是需要更新数据时,都伴随着一个发向服务器的请求。当服务器返回响应时,整个页面会重载,并渲染新页面。
这种模式会带来一些问题:
首先,频繁更新页面会牺牲性能,浪费服务器资源,同时降低用户体验。另外,对于一些操作性很强的程序来说,重载页面会显得很不合理。
比如我们做了一个Web计算器程序,所有的按钮和显示屏幕都很逼真,但当我们单击“等于”按钮时,要等到页面重新加载后才在显示屏幕上看到结果,这显然会严重影响用户体验。
但是AJAX技术可以完美地解决这些问题。
AJAX是什么
AJAX指异步Javascript和XML(Asynchronous JavaScript And XML),它不是编程语言或通信协议,而是一系列技术的组合体。
简单来说,AJAX基于XMLHttpRequest(https://xhr.spec.whatwg.org/)让我们可以在不重载页面的情况下和服务器进行数据交换。
加上JavaScript和 DOM(Document Object Model,文档对象模型),就可以在接收到响应数据后局部更新页面。
而XML指的则是数据的交互格式,也可以是纯文本(Plain Text)、HTML或JSON。顺便说一句, XMLHttpRequest不仅支持HTTP协议,还支持FILE和FTP协议
以删除某个资源为例,在普通的程序中流程如下:
- 当“删除”按钮被单击时会发送一个请求,页面变空白,在接收到响应前无法进行其他操作
- 服务器端接收请求,执行删除操作,返回包含整个页面的响应。
- 客户端接收到响应,重载整个页面。
而使用AJAX技术时的流程如下:
-
当单击“删除”按钮时,客户端在后台发送一个异步请求,页面不变,在接收响应前可以进行其他操作。
-
服务器端接收请求后执行删除操作,返回提示消息或是无内容 的204响应。
-
客户端接收到响应,使用JavaScript更新页面,移除资源对应的页面元素。
使用jQuery发送AJAX请求
jQuery是流行的JavaScript库,它包装了JavaScript,让我们通过更简单的方式编写JavaScript代码。
对于AJAX,它提供了多个相关的方法, 使用它可以很方便地实现AJAX操作。
我们将使用全局jQuery函数ajax()发送AJAX请 求。ajax()函数是底层函数,有丰富的自定义配置,支持的主要参数如表所示
返回局部数据,有常见的三种类型:
- 纯文本或局部HTML模板:纯文本可以在JavaScript用来直接替换页面中的文本值,而局部HTML则可以直接到插入页面中,比如返回评论列表:
@app.route('/comments/<int:post_id>')
def get_comments(post_id):
...
return render_template('comments.html')
- JSON数据:JSON数据可以在JavaScript中直接操作:
在jQuery中的ajax()方法的success回调中,响应主体中的JSON字符串会被解析为JSON对象,我们可以直接获取并进行操作。
@app.route('/profile/<int:user_id>')
def get_profile(user_id):
...
return jsonify(username=username, bio=bio)
- 空值:有些时候,程序中的某些接收AJAX请求的视图并不需要返回数据给客户端,比如用来删除文章的视图。这时我们可以直接返回空值,并 将状态码指定为204(表示无内容)
@app.route('/post/delete/<int:post_id>', methods=['DELETE'])
def delete_post(post_id):
...
return '', 204
异步加载长文章
from jinja2.utils import generate_lorem_ipsum
@app.route('/post')
def show_post():
#生成两段随机文本 n参数用来指定段落的数量
post_body = generate_lorem_ipsum(n=2)
return '''
<h1>A very long post</h1>
<div class="body">%s</div>
<button id="load">Load More</button>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function() {
$('#load').click(function() {
$.ajax({
url: '/more', // 目标URL
type: 'get', // 请求方法
success: function(data){ // 返回2XX响应后触发的回调函数
$('.body').append(data); // 将返回的响应插入到页面中
}
})
})
})</script>''' % post_body
文章的随机正文通过Jinja2提供的generate_lorem_ipsum()函数生 成,n参数用来指定段落的数量。
按钮下面是两个 <script></script>
代码块,第一个script从CDN加载jQuery资源。
$.ajax()等同于jQuery.ajax()
$(’#load’)被称为选择器
在这个回调函数中,我们使用$.ajax()
方法发送一个AJAX请求到服务器,通过url将目标URL设为“/more”,通过type参数将请求的类型设为GET。
当请求成功处理并返回2XX响应时(另外还包括304响应),会触发success回调函数。
success回调函数接收的第一个参数为服务器端返回的响应主体,在这个回调函数中,我们在文章正文 (通过$(’.body’)选择)底部使用append()方法插入返回的data数据。