前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >利用Ajax提升网页渲染速度——以Highcharts为例

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

作者头像
benny
发布2018-07-26 14:42:34
7790
发布2018-07-26 14:42:34
举报
文章被收录于专栏:程序员的碎碎念

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

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

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

Django响应请求

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

代码语言:javascript
复制
# 若显示不全,请滑动屏幕
def get_trend_by_word(request):
    ...

    #把request中的变量值提取出来, 用于处理
    keyword = request.GET['keyword']
    city = request.GET['city']

    ...
    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代码片

代码语言:javascript
复制
# 若显示不全,请滑动屏幕
    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代码片

代码语言:javascript
复制
# 若显示不全,请滑动屏幕
  $(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 = ret
              console.log(series)
            });
          if (!e.seriesOptions) {
            var chart = this,
            drilldowns = {
              type:'line',
            },
          series = drilldowns;
          // Show the loading label
          chart.showLoading('正在获取数据...');
          setTimeout(function () {
            chart.hideLoading();
            chart.addSeriesAsDrilldown(e.point, series);
          }, 1000);
          }
          }
        }
        },

     ...

    });
  });

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

代码语言:javascript
复制
# 若显示不全,请滑动屏幕
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) is False}

    ...

    # 把该工资趋势所有数据一次性发送到前端渲染
    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代码片

代码语言:javascript
复制
# 若显示不全,请滑动屏幕
# 根据网页请求的关键词, 把对应关键词的工资趋势数据保存下来, 发送到前端
def get_trend_by_word(request):
    # use Ajax to reduce dom
    keyword = 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]}

    return JsonResponse(salary_trend, safe=False)

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

今日作者: 光光同学_

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员的碎碎念 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前端发送请求
  • Django响应请求
  • 参考资料
  • 代码对比
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档