高性能的js第三方库——lodash Underscoreasyncmd5及moment
Posted wheatcatcher
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高性能的js第三方库——lodash Underscoreasyncmd5及moment相关的知识,希望对你有一定的参考价值。
背景:为了实现某些功能,如:数据排序、分组、筛选、深拷贝等,自己写的函数或网上搜索处理的转换函数质量无法保证,这时直接使用成熟的js第三方库是首选。
*注:“framework(框架)”,“library(库)”和“tool(工具)” 可以根据情境,在不同时期,对不同的人,意味着不同的东西。
一、Lodash 和 Underscore(推荐参考阮一峰的日志)
1.优点:将 Lodash 和 Underscore 放在一起,因为它们提供了数百个功能性的 javascript 实用程序来补充原生字符串,数字,数组和其他原始对象的方法。二者有一些功能性的重叠,所以你不太可能在一个项目中同事需要这两个库。
它在客户端使用率似乎很低,但是可以在服务器端的 Node.js 应用程序中使用这两个库。
- 小而简单
- 拥有优质文档,易于学习
- 与大多数库和框架兼容
- 不扩展内置对象
- 可以在客户端或服务器上使用
2.缺点:
- 有些方法只适用于ES2015及更高版本的 JavaScript
实例:
import * as _ from ‘lodash‘ import * as _s from ‘underscore‘ //数组去重对比 _.uniq([1,1,3]) // => [1,3] _s.uniq([1, 2, 1, 4, 1, 3]); => [1, 2, 4, 3]
分别是:异步请求、加密、日期转换
实例:
import * as _async from ‘async‘ import * as _moment from ‘moment‘ import * as _md5 from ‘md5‘ shunXuAsync() // 异步 顺序执行 let task1 = function (callback) console.log("task1"); callback(null, "task1") let task2 = function (callback) console.log("task2"); callback(null, "task2") // callback("err","task2") // null改为err ,如果中途发生错误,则将错误传递到回调函数,并停止执行后面的函数 let task3 = function (callback) console.log("task3"); callback(null, "task3") _async.series([task1, task2, task3], function (err, result) console.log("series"); if (err) console.log(err); console.log(result); ) console.log(_moment().format(‘MMMM Do YYYY, h:mm:ss a‘)) //当前时间+格式 console.log(md5(‘message‘));//78e731027d8fd50ed642340b7c9a63b3
附:常用的几个Lodash函数
import _ from ‘lodash‘ // 1.深拷贝 var objects = [ ‘a‘: 1 , ‘b‘: 2 ]; var deep = _.cloneDeep(objects); console.log(deep[0] === objects[0]); // => false //2.分组 _.groupBy([6.1, 4.2, 6.3], Math.floor); // => ‘4‘: [4.2], ‘6‘: [6.1, 6.3] // The `_.property` iteratee shorthand. _.groupBy([‘one‘, ‘two‘, ‘three‘], ‘length‘); // => ‘3‘: [‘one‘, ‘two‘], ‘5‘: [‘three‘] //3. 合并key、value _.zipObject([‘a‘, ‘b‘], [1, 2]); // => ‘a‘: 1, ‘b‘: 2 //4.深比较不同 var object = ‘a‘: 1 ; var other = ‘a‘: 1 ; _.isEqual(object, other); // => true object === other; // => false //5.数组对象去重 var objects = [ ‘x‘: 1, ‘y‘: 2 , ‘x‘: 2, ‘y‘: 1 , ‘x‘: 1, ‘y‘: 2 ]; _.uniqWith(objects, _.isEqual); // => [ ‘x‘: 1, ‘y‘: 2 , ‘x‘: 2, ‘y‘: 1 ] //6.是否为空:对象、数组、布尔值、数值 _.isEmpty(null); // => true _.isEmpty(true); // => true _.isEmpty(1); // => true _.isEmpty([1, 2, 3]); // => false _.isEmpty( ‘a‘: 1 ); // => false
对比一下,自己写一个异步请求函数需要怎么做:
// 1.分布打包请求 jarBuildChange(params) this.buildResult = ‘‘ this.loadingBuild = true this.loadingBuildResult = true const stepCallback = (res) => console.log(res, ‘stepCallback‘) if (res.err_code === ‘0‘) this.loadingBuildResult = false this.$message.success(‘日志已更新,正在打包中......‘) this.buildResult += `\\n$res.info` else this.loadingBuild = false this.loadingBuildResult = false this.$message.error(res.err_desc) this.buildResult = `打包失败:\\n错误码:$res.error_code\\n$res.err_desc` const lastCallback = (res) => console.log(res, ‘lastCallback‘) if (res.err_code === ‘0‘) this.loadingBuild = false this.buildResult += `$res.err_desc` this.getBuildHistory() this.custom.jarname = res.jarname this.$message.success(‘打包结束,打包记录已更新!‘) else this.loadingBuild = false this.loadingBuildResult = false this.$message.error(res.err_desc) this.buildResult = `打包失败:\\n错误码:$res.error_code\\n$res.err_desc` const timeoutCallback = (res) => console.log(res, ‘timeoutCallback‘) this.loadingBuild = false this.loadingBuildResult = false this.getBuildHistory() this.$message.error(res.err_desc) this.buildResult = `打包超时:\\n错误码:$res.error_code\\n$res.err_desc` jarBuildResult(params, stepCallback, lastCallback, timeoutCallback) //2.打包结果持续拉取:参数+开始返回+最后返回+超时返回 export function jarBuildResult(params, stepCallback, lastCallback, timeoutCallback) stepRequest(_config.jarpackage_build, params || , stepCallback, lastCallback, 3600000, timeoutCallback) //3.分布执行 export const stepRequest = ( url, // 要封装调用接口路径 data, // 封装调用接口请求数据 stepCallback, // 中间步骤response回调,参数为response json lastCallback, // 调用最后response回调,参数为response json timeoutMs, // 执行超时时间 timeoutCallback // 超时回调,无参数 ) => let nextSeqid = 0 let isSuccDone = false let timeoutChecker = new TimeoutChecker(timeoutMs) let uuid = makeUuid() data[‘step_track_uuid‘] = uuid const doMainRequest = () => axios( url: url, method: ‘post‘, data: data, timeout: 3600000 ).then(function (response) return response ).catch(function (error) console.log(error) ) const handleResponseList = (stepRes) => for (let response of stepRes.data.response_list) // eslint-disable-next-line stepCallback(eval(‘(‘ + response + ‘)‘)) const handleTimeout = () => if (timeoutCallback) let func = timeoutCallback timeoutCallback = null func() let interval = setInterval(() => if (isSuccDone) clearInterval(interval) handleTimeout() else if (timeoutChecker.isTimeout()) clearInterval(interval) handleTimeout() else getResponseStepList(uuid, nextSeqid).then((stepRes) => if (isSuccDone) clearInterval(interval) else nextSeqid = stepRes.data.next_seqid handleResponseList(stepRes) ) , 2000) doMainRequest().then(res => if (!timeoutChecker.isTimeout()) isSuccDone = true clearInterval(interval) getResponseStepList(uuid, nextSeqid).then((stepRes) => handleResponseList(stepRes) lastCallback(res.data) ) else handleTimeout() )
生成随机数uuid:
function makeUuid () var s = [] var hexDigits = ‘0123456789abcdef‘ for (var i = 0; i < 36; i++) s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1) // bits 12-15 of the time_hi_and_version field to 0010 s[14] = ‘4‘ // bits 6-7 of the clock_seq_hi_and_reserved to 01 s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) s[8] = s[13] = s[18] = s[23] = ‘-‘ var uuid = s.join(‘‘) return uuid
获取分布列表:
export const getResponseStepList = (uuid, seqid) => axios.post(CONFIG_PREFIX + ‘/response/steplist‘, step_track_uuid: uuid, step_next_seqid: seqid ).then(function (response) return response ).catch(function (error) console.log(error) )
axios异步封装:
import CONFIG_PREFIX from ‘./config‘ // import axios from ‘axios‘; import axios from ‘./axios.js‘ /** * axios 配置 * 请求超时 * 登录携带cookie */ import axios from ‘axios‘// 让ajax携带cookie import doLogin from ‘./login‘ import Message from ‘element-ui‘ import queryString from ‘query-string‘ import router from ‘../../src/router‘ // import Vue from ‘vue‘ axios.defaults.timeout = 3600000 // 请求超时 axios.defaults.withCredentials = true function goNotAllowedPage () // document.body.innerhtml = "<div id=‘app‘></div>" // let app = new Vue( // el: ‘#app‘, // template: ‘<div style="margin-top: 100px"><p style="text-align: center">暂无此模块权限,如需访问,请联系XXX申请权限。</p></div>‘ // ) // app.$destroy() router.push( path: ‘/web/notallowed‘ ) //* ************************************************ http request 请求拦截器 const parsed = queryString.parse(location.search) axios.interceptors.request.use( config => if (parsed.__test) // e2e测试 config.url = config.url.trim() + ‘?v__test=‘ + parsed.__test return config , err => return Promise.reject(err) ) //* ******************************************** http response 返回拦截器 axios.interceptors.response.use( response => if (response.status === 200 && response.data) const res = response.data // 接口4001统一处理,4001意思是没有登录状态,需要重新登录 if (res.err_code === ‘4001‘) doLogin() // eslint-disable-next-line return Promise.reject("error"); else if (res.err_code === ‘4003‘) goNotAllowedPage() res.err_code = ‘0‘ return response else if (res.err_code === ‘4005‘) Message.error(‘请联系owner,无法进行修改‘) // eslint-disable-next-line return response; else if (res.app_config || res.err_code === ‘0‘) // proj/app/get此请求无返回err_code=0 return response else // const desc = res.err_desc ? ‘操作失败错误,错误码:‘ + res.err_code + ‘,错误信息:‘ + res.err_desc : ‘返回值错误!‘; //暂时注释 // Message.warning(desc); return response , error => // console.log(error, ‘跨越问题无法获取状态码‘) if (error && error.response) if (error.response.status === 400) Message.error(‘请求错误(400)‘) else if (error.response.status === 404) Message.error(‘请求出错(404)‘) else if (error.response.status === 408) Message.error(‘请求超时(408)‘) else if (error.response.status === 500) Message.error(‘服务器错误(500)‘) else if (error.response.status === 501) Message.error(‘服务未实现(501)‘) else if (error.response.status === 502) Message.error(‘网络错误(502)‘) else if (error.response.status === 503) Message.error(‘服务不可用(503)‘) else if (error.response.status === 504) Message.error(‘网络超时(504)‘) else Message.error(`连接出错($error.response.status)!`) else Message.error(error) return Promise.reject(error) ) export default axios //配置参数: /** 【统一配置url入口】 * 统一URL:cgi_domain_prefix * 代理URL(正式/测试) * 获取ticket:getPar(par) */ /* eslint-disable */ let cgi_domain_prefix = MY_HOST // let cgi_domain_prefix=‘http://localhost:8080‘; // if (process.env.NODE_ENV === ‘production‘) // cgi_domain_prefix = "http://xxx:8080"; // else // cgi_domain_prefix = "http://xxx:8000"; // export const CONFIG_PREFIX = cgi_domain_prefix //* ********************************************************************************************************** // 获取登录后的ticket:这里可以使用js第三方库【cookie.js】 function getPar (par) // 获取当前URL // console.log("document.location.href", document.location.href) let local_url = document.location.href // 获取要取得的get参数位置 let get = local_url.indexOf(par + ‘=‘) // console.log("document.location.href 2", document.location.href) if (get === -1) return false // 截取字符串 let get_par = local_url.slice(par.length + get + 1) // 判断截取后的字符串是否还有其他get参数 let nextPar = get_par.indexOf(‘&‘) if (nextPar !== -1) get_par = get_par.slice(0, nextPar) return get_par const REAL_TICKER = getPar(‘ticket‘) ? ‘?ticket=‘ + getPar(‘ticket‘) : ‘‘ // 实例: // 1.1.登录 export const GET_USER = cgi_domain_prefix + ‘/user/rtxname‘ + REAL_TICKER // 1.2.注销 export const GET_LOGOUT = cgi_domain_prefix + ‘/user/logout‘
以上是关于高性能的js第三方库——lodash Underscoreasyncmd5及moment的主要内容,如果未能解决你的问题,请参考以下文章
lodash入门,使用 。throttle和debounce
JavaScript工具库——Lodash.js介绍安装及使用
Lodash一个一致性模块化高性能的JavaScript实用工具库