利用Ajax提升网页渲染速度——以Highcharts为例

Posted 程序员的碎碎念

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用Ajax提升网页渲染速度——以Highcharts为例相关的知识,希望对你有一定的参考价值。


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

利用Ajax提升网页渲染速度——以Highcharts为例利用Ajax提升网页渲染速度——以Highcharts为例利用Ajax提升网页渲染速度——以Highcharts为例

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中供后面的图表渲染.

 
   
   
 
  1. # 若显示不全,请滑动屏幕

  2. $.get('/get_trend_by_word/', {'keyword':String(e.point.name), 'city': '东莞'}, function(ret){          

  3.              series = ret

  4.            });


Django响应请求

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

 
   
   
 
  1. # 若显示不全,请滑动屏幕

  2. def get_trend_by_word(request):

  3.    ...

  4.    #把request中的变量值提取出来, 用于处理

  5.    keyword = request.GET['keyword']

  6.    city = request.GET['city']

  7.    ...

  8.    return JsonResponse(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代码片

 
   
   
 
  1. # 若显示不全,请滑动屏幕

  2.    var drilldown = {

  3.        series: [

  4.            {% for k, v in series1.items %}

  5.                {

  6.                type: 'line',

  7.                id: '{{ k }}',

  8.                name: '{{ k }}',

  9.                data: [

  10.                    {% for i in v %}

  11.                        {% for j in i %}

  12.                            {% if forloop.first %} ['{{ j | date:"Y-m-d" }}', {% endif %}

  13.                            {% if forloop.last %} {{ j }}], {% endif %}

  14.                        {% endfor %}

  15.                    {% endfor %}

  16.                ]

  17.                },

  18.            {% endfor %}

  19.            ]};

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

 
   
   
 
  1. # 若显示不全,请滑动屏幕

  2.  $(function (){

  3.    $('#trend').highcharts({

  4.      chart: {

  5.        type: 'column',

  6.        events:{

  7.          drillup: function(e) {

  8.              // 上钻回调事件

  9.              console.log(e.seriesOptions);

  10.            },

  11.          drilldown: function (e) {

  12.           // 重点在这一句

  13.            $.get('/get_trend_by_word/', {'keyword':String(e.point.name), 'city': '东莞'}, function(ret){

  14.              console.log(ret.Animals)

  15.              series = ret

  16.              console.log(series)

  17.            });

  18.          if (!e.seriesOptions) {

  19.            var chart = this,

  20.            drilldowns = {

  21.              type:'line',

  22.            },

  23.          series = drilldowns;

  24.          // Show the loading label

  25.          chart.showLoading('正在获取数据...');

  26.          setTimeout(function () {

  27.            chart.hideLoading();

  28.            chart.addSeriesAsDrilldown(e.point, series);

  29.          }, 1000);

  30.          }

  31.          }

  32.        }

  33.        },

  34.     ...

  35.    });

  36.  });

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

 
   
   
 
  1. # 若显示不全,请滑动屏幕

  2. def dataViewer(request):

  3.    ...

  4.    # 使用一个循环将所有关键词的工资趋势一次性保存在一个字典里

  5.    trends_dict = {kd: get_salary_trend(job_info, kd, city)

  6.            for kd in top_keyword if (get_salary_trend(job_info, kd, city).empty) is False}

  7.    ...

  8.    # 把该工资趋势所有数据一次性发送到前端渲染

  9.    context = {

  10.        'cities': items[:20],

  11.        'series': series.sort_values()[::-1][:25],

  12.        'keyword_dict': kd_salary,

  13.        'top_job_counts':job_count_rank.sort_values()[::-1][:25],

  14.        # 按索引排序

  15.        'trends_dict': Series(trends_dict).sort_index()[::-1][:25],

  16.        'city':city,

  17.    }

  18.    return render(request, 'data_viewer.html', context)

  19. def get_salary_trend(job_info, keyword, city):

  20.    # 获取工资趋势

  21.    if(city != '全国' or city != '异地招聘'):

  22.        pattern = r'^(' + city + '|' + city + ')'

  23.        # items = JobField.objects(__raw__={'key_word':keyword, 'job_city': city})

  24.        items = JobField.objects(Q(key_word=keyword) & Q(job_city=city))

  25.    else:

  26.        # items = JobField.objects(__raw__={'key_word':keyword})

  27.        items = JobField.objects(key_word=keyword)

  28.    salary_trend_list = []

  29.    dates = items.distinct("create_time")

  30.    for day in dates:

  31.        item = items(__raw__={'create_time': day})

  32.        salary_avg = item.average('salary_avg')

  33.        salary_trend = [day, round(salary_avg, 2)]

  34.        salary_trend_list.append(salary_trend)

  35.    salary_trend = dict(salary_trend_list)

  36.    salary_trend = Series(salary_trend)

  37.    return salary_trend

下面这段是修改后的python代码片

 
   
   
 
  1. # 若显示不全,请滑动屏幕

  2. # 根据网页请求的关键词, 把对应关键词的工资趋势数据保存下来, 发送到前端

  3. def get_trend_by_word(request):

  4.    # use Ajax to reduce dom

  5.    keyword = request.GET['keyword']

  6.    city = request.GET['city']

  7.    keyword = str(keyword)

  8.    city = str(city)

  9.    # 获取工资趋势

  10.    if(city != '全国' or city != '异地招聘'):

  11.        pattern = r'^(' + city + '|' + city + ')'

  12.        items = JobField.objects(Q(key_word=keyword) & Q(job_city=city))

  13.    else:

  14.        items = JobField.objects(key_word=keyword)

  15.    salary_trend_list = []

  16.    dates = items.distinct("create_time")

  17.    for day in dates:

  18.        item = items(__raw__={'create_time': day})

  19.        salary_avg = item.average('salary_avg')

  20.        salary_trend = [str(day)[0:10], round(salary_avg, 2)]

  21.        salary_trend_list.append(salary_trend)

  22.    salary_trend_list = Series(salary_trend_list).sort_index()[::-1]

  23.    salary_trend = {'type': 'line', 'name': keyword, 'data':[i for i in salary_trend_list]}

  24.    return JsonResponse(salary_trend, safe=False)



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


今日作者: 光光同学_

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


以上是关于利用Ajax提升网页渲染速度——以Highcharts为例的主要内容,如果未能解决你的问题,请参考以下文章

网页渲染优化和JS性能提升

ajax删除数据(不跳转页面)

数据之路 - Python爬虫 - Ajax

提升node-mapnik渲染速度

减慢浏览器渲染速度

前后端分离