前端开发学习笔记(一)

前言

在做一个叫计算平台的项目,主要是将机器学习、深度学习和大数据结合在一起,对标该领域中,阿里的计算平台、第四范式的先知平台等知名项目。目前,我们实现了基于Spark的可视化ETL功能,还有很多事情要做。

在这个项目中,用到了Vue.js的技术栈。为了加快项目进度,笔者还是在全沾的道路上越走越远,所以特地记录一路上的问题。

Vue.js

入门Vue.js不算特别难,一定要多看几遍官方文档!一个完整的初级Demo大致涨这样:

项目Demo地址: hello-vue

初学时,搞不清单文件组件。没人带,就直接想用高级的姿势,是可怕的。既然初学,还是得一步一步来…

前后端通讯:unicode/string

Case: 前端通过JSON将string数据转发的Python后端,结果该类型变成了Unicode类型。废掉了如下代码:

if isinstance(data, str):
    do somethings....

按道理说,data应该是string类型才对。

后端将js ajax转发来的数据通过flask.request.get_json()方法解析,相关方法:

// 获取数据
s = request.get_json()

// get_json()方法
def get_json(self, force=False, silent=False, cache=True):
        """Parse and return the data as JSON. If the mimetype does not
        indicate JSON (:mimetype:`application/json`, see
        :meth:`is_json`), this returns ``None`` unless ``force`` is
        true. If parsing fails, :meth:`on_json_loading_failed` is called
        and its return value is used as the return value.

        :param force: Ignore the mimetype and always try to parse JSON.
        :param silent: Silence parsing errors and return ``None``
            instead.
        :param cache: Store the parsed JSON to return for subsequent
            calls.
        """
        if cache and self._cached_json[silent] is not Ellipsis:
            return self._cached_json[silent]

        if not (force or self.is_json):
            return None

        data = self._get_data_for_json(cache=cache)

        try:
            rv = json.loads(data)
        except ValueError as e:
            if silent:
                rv = None
                if cache:
                    normal_rv, _ = self._cached_json
                    self._cached_json = (normal_rv, rv)
            else:
                rv = self.on_json_loading_failed(e)
                if cache:
                    _, silent_rv = self._cached_json
                    self._cached_json = (rv, silent_rv)
        else:
            if cache:
                self._cached_json = (rv, rv)

        return rv

原因:

# 导入环境
from flask import json

# 测试数据集
s = '{"user_id":"zhangshan","plan_id":"m00_for_newOperator","operator_type":"map","fast_mode":false,"module_name":"test_map1","func_name":["map1"],"operator_resource":["test_map1"],"input_rows":[{"table_name":"id_t3","fields":[{"col_name":"e","data_type":"string"},{"col_name":"f","data_type":"boolean"},{"col_name":"g","data_type":"array<double>[1]"},{"col_name":"h","data_type":"binary"},{"col_name":"i","data_type":"array<binary>[1]"},{"col_name":"a","data_type":"string"},{"col_name":"b","data_type":"double"},{"col_name":"c","data_type":"long"},{"col_name":"d","data_type":"string"}],"values":[["2018-11-28 12:22:59.862776",true,[11],"f1 e4",["01 02"],"hello",3.14,1,"2018-11-28"]]}]}'

# python 2.7
>>> json.loads(s)
>>> {u'plan_id': u'm00_for_newOperator', u'input_rows': [{u'values': [[u'2018-11-28 12:22:59.862776', True, [11], u'f1 e4', [u'01 02'], u'hello', 3.14, 1, u'2018-11-28']], u'fields': [{u'col_name': u'e', u'data_type': u'string'}, {u'col_name': u'f', u'data_type': u'boolean'}, {u'col_name': u'g', u'data_type': u'array<double>[1]'}, {u'col_name': u'h', u'data_type': u'binary'}, {u'col_name': u'i', u'data_type': u'array<binary>[1]'}, {u'col_name': u'a', u'data_type': u'string'}, {u'col_name': u'b', u'data_type': u'double'}, {u'col_name': u'c', u'data_type': u'long'}, {u'col_name': u'd', u'data_type': u'string'}], u'table_name': u'id_t3'}], u'func_name': [u'map1'], u'fast_mode': False, u'operator_resource': [u'test_map1'], u'module_name': u'test_map1', u'user_id': u'zhangshan', u'operator_type': u'map'}

# python 3.5
>>> json.loads(s)
>>> {'user_id': 'zhangshan', 'plan_id': 'm00_for_newOperator', 'func_name': ['map1'], 'input_rows': [{'fields': [{'data_type': 'string', 'col_name': 'e'}, {'data_type': 'boolean', 'col_name': 'f'}, {'data_type': 'array<double>[1]', 'col_name': 'g'}, {'data_type': 'binary', 'col_name': 'h'}, {'data_type': 'array<binary>[1]', 'col_name': 'i'}, {'data_type': 'string', 'col_name': 'a'}, {'data_type': 'double', 'col_name': 'b'}, {'data_type': 'long', 'col_name': 'c'}, {'data_type': 'string', 'col_name': 'd'}], 'values': [['2018-11-28 12:22:59.862776', True, [11], 'f1 e4', ['01 02'], 'hello', 3.14, 1, '2018-11-28']], 'table_name': 'id_t3'}], 'module_name': 'test_map1', 'operator_resource': ['test_map1'], 'fast_mode': False, 'operator_type': 'map'}

做的项目同时支持python2和3的话,需要注意该问题。

求树的深度

Case: 需要获取用户输入的多维数组的维度。该问题,即求解树的深度:

// 获取数组的维度
getArrayDim: function getDeepth(array) {
    function sum(arr, flag) {
      return arr.reduce(function (total, item) {
        var totalDeepth ;
        if (Array.isArray(item)) {
          totalDeepth = sum(item, flag + 1);
        }
        return totalDeepth > total ? totalDeepth : total;
      }, flag)
    }
    return sum(array, 1);
}

递归遍历多维数组

Case: 用户输入一个多维数组,该数组的值类型已被固定(long, int, string…)。

// 判断array内部元素的值类型
checkArrayValueType: function checkArrayValue(type, realType, obj) {
    var res = { status: 0, msg: ""} ;
    for (var a in obj) {
      if (obj[a] instanceof Array) {
        res = checkArrayValue(type,obj[a]); //递归遍历
      } else {
        if(typeof(obj[a]) === type){
          continue
        }
        res.status = 1;
        res.msg = '数据项:' + obj[a] +', 不是' +realType + '类型; ';
        return res;
      }
    }
    return res;
},

检测Binary(hex)

Case: 用户输入一段字符串,需要知道是否是hex型的binary。用户输入要求为:按空格分割为2位, 不能以0x开头,如:’f1 01 e4’, ‘01 02 03’。

// check for binary, 需要其他地方做split和trim
checkBinary: function isBinary(item) {
    var validChars = "0123456789abcdef";
    var isBinary = true;
    var char;
    for (var i = 0; i < item.length && isBinary == true; i++){
      char = item.toLowerCase().charAt(i);
      if (validChars.indexOf(char) == -1) {
        isBinary = false;
      }
    }
    return isBinary;
},

结语

记录了一些demo和实际开发的case, 有时间继续更。