优化ajax加载数据速度,利用Ajax提升网页渲染速度——以Highcharts为例

092011eb7e46efd76a1236943c00be8d.png

先来看看速度优化对比(这里用了 Django的 DebugToolbar库来查看状态)

608235a1f9655458fd61f045e94654cd.png

be18ef765bcd26d35647310ee30887cf.png

d2c1639aefa0c8f80bf640321c83b63f.png

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。AJAX 不是新的编程语言,而是一种使用现有标准的新方法。AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

在项目一开始时, 为了呈现数据的工资趋势图, 把所有的关键词趋势数据一次性处理后发送至前端, 造成DOM数目过多, 导致网页渲染数据极慢, 到了无法忍受的1分多钟的时间.

后面使用Ajax的 get方法, 只对于要下钻的关键词工资趋势获取对应数据, 最终把时间压到了20秒以内(由于整个页面还包含其他图表, 如果只有单个图表, 时间可以进一步缩短)

前端发送请求

下面的代码片就是添加了 get方法后的highcharts片段.

这段代码的意思是用 get函数发送请求, 请求的内容是 {'keyword':String(e.point.name),'city':'东莞'}

url是 /get_trend_by_word/, 这里的url会交由Django后台的路由识别出对应函数进行处理.

处理后的返回数据保存在 ret中. 函数体内部把返回的数据 ret保存在 series中供后面的图表渲染.

# 若显示不全,请滑动屏幕$.get('/get_trend_by_word/', {'keyword':String(e.point.name), 'city': '东莞'}, function(ret){series = ret});

Django响应请求

在Django的视图模块 views.py中, 响应ajax请求, 处理完毕后发送回前端

# 若显示不全,请滑动屏幕def get_trend_by_word(request):...#把request中的变量值提取出来, 用于处理keyword = request.GET['keyword']city = request.GET['city']...returnJsonResponse(salary_trend, safe=False)

参考资料

关于HighCharts的Ajax例子可以参考官方文档 https://www.hcharts.cn/docs/ajax

菜鸟教程 http://www.runoob.com/ajax/ajax-tutorial.html

还在修改中的项目, 欢迎吐槽(逃

https://github.com/FesonX/JobDataViewer

代码对比

(觉得太丑可以直接跳过)

下面这段是修改前的js代码片

# 若显示不全,请滑动屏幕var drilldown = {series: [{% for k, v in series1.items %}{type: 'line',id: '{{ k }}',name: '{{ k }}',data: [{% for i in v %}{% for j in i %}{% if forloop.first %} ['{{ j | date:"Y-m-d" }}', {% endif %}{% if forloop.last %} {{ j }}], {% endif %}{% endfor %}{% endfor %}]},{% endfor %}]};下面这段是修改后的js代码片

# 若显示不全,请滑动屏幕$(function (){$('#trend').highcharts({chart: {type: 'column',events:{drillup: function(e) {// 上钻回调事件console.log(e.seriesOptions);},drilldown: function (e) {// 重点在这一句$.get('/get_trend_by_word/', {'keyword':String(e.point.name), 'city': '东莞'}, function(ret){console.log(ret.Animals)series = retconsole.log(series)});if (!e.seriesOptions) {var chart = this,drilldowns = {type:'line',},series = drilldowns;// Show the loading labelchart.showLoading('正在获取数据...');setTimeout(function () {chart.hideLoading();chart.addSeriesAsDrilldown(e.point, series);}, 1000);}}}},...});});下面这段是修改前的python代码片

# 若显示不全,请滑动屏幕def dataViewer(request):...# 使用一个循环将所有关键词的工资趋势一次性保存在一个字典里trends_dict = {kd: get_salary_trend(job_info, kd, city)for kd in top_keyword if (get_salary_trend(job_info, kd, city).empty) isFalse}...# 把该工资趋势所有数据一次性发送到前端渲染context = {'cities': items[:20],'series': series.sort_values()[::-1][:25],'keyword_dict': kd_salary,'top_job_counts':job_count_rank.sort_values()[::-1][:25],# 按索引排序'trends_dict': Series(trends_dict).sort_index()[::-1][:25],'city':city,}return render(request, 'data_viewer.html', context)def get_salary_trend(job_info, keyword, city):# 获取工资趋势if(city != '全国'or city != '异地招聘'):pattern = r'^(' + city + '|' + city + ')'# items = JobField.objects(__raw__={'key_word':keyword, 'job_city': city})items = JobField.objects(Q(key_word=keyword) & Q(job_city=city))else:# items = JobField.objects(__raw__={'key_word':keyword})items = JobField.objects(key_word=keyword)salary_trend_list = []dates = items.distinct("create_time")for day in dates:item = items(__raw__={'create_time': day})salary_avg = item.average('salary_avg')salary_trend = [day, round(salary_avg, 2)]salary_trend_list.append(salary_trend)salary_trend = dict(salary_trend_list)salary_trend = Series(salary_trend)return salary_trend下面这段是修改后的python代码片

# 若显示不全,请滑动屏幕# 根据网页请求的关键词, 把对应关键词的工资趋势数据保存下来, 发送到前端def get_trend_by_word(request):# use Ajax to reduce domkeyword = request.GET['keyword']city = request.GET['city']keyword = str(keyword)city = str(city)# 获取工资趋势if(city != '全国'or city != '异地招聘'):pattern = r'^(' + city + '|' + city + ')'items = JobField.objects(Q(key_word=keyword) & Q(job_city=city))else:items = JobField.objects(key_word=keyword)salary_trend_list = []dates = items.distinct("create_time")for day in dates:item = items(__raw__={'create_time': day})salary_avg = item.average('salary_avg')salary_trend = [str(day)[0:10], round(salary_avg, 2)]salary_trend_list.append(salary_trend)salary_trend_list = Series(salary_trend_list).sort_index()[::-1]salary_trend = {'type': 'line', 'name': keyword, 'data':[i for i in salary_trend_list]}returnJsonResponse(salary_trend, safe=False)

入门小白, 欢迎大家指出错误, 技术交流

dbfb66287e6282ea0550847f95f7ea92.png

今日作者: 光光同学_

不爱看电影的摄影师不是好的程序员

举报/反馈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值