背景:为了实现某些功能,如:数据排序、分组、筛选、深拷贝等,自己写的函数或网上搜索处理的转换函数质量无法保证,这时直接使用成熟的js第三方库是首选。

*注:“framework(框架)”,“library(库)”和“tool(工具)” 可以根据情境,在不同时期,对不同的人,意味着不同的东西。

一、LodashUnderscore(推荐参考阮一峰的日志)

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]

二、asyncmd5moment

分别是:异步请求、加密、日期转换

实例:

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函数

【浅拷贝】:

var objects = [{ 'a': 1 }, { 'b': 2 }];

var shallow = _.clone(objects);
console.log(shallow[0] === objects[0]);
// => true

如图:

【深拷贝】:

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 //7.多维数组合并为一维数组
 _.flattenDeep([1, [2, [3, [4]], 5]]);

 // => [1, 2, 3, 4, 5]
//8.根据某个字段排序

const users = [
{ 'user': 'fred', 'age': 48 },
{ 'user': 'barney', 'age': 34 },
{ 'user': 'fred', 'age': 42 },
{ 'user': 'barney', 'age': 36 }
];

// 以 `user` 升序排序 再 以 `age` 降序排序。
_.orderBy(users, ['user', 'age'], ['asc', 'desc']);

// 9 .简单数组的排序

_.sortBy(arr, function(item) {
  return item.createTime;
});

_.sortBy(arr, function(item) {
return -item.createTime;
});

// 10.判断是否有重复

_.uniq([2, 1, 2])
// => [2, 1]

if(_.uniq(arr) = arr.lengh){ // 判断去重后的数组长度

}

//补:其他引用写法:

import {flattenDeep} from 'lodash' // 多维数组转换为一维数组

对比一下,自己写一个异步请求函数需要怎么做:

// 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、 Underscore、async、md5及moment的更多相关文章

  1. js工具库---Lodash

    Lodash是一个一致性.模块化.高性能的 JavaScript 实用工具库 为什么选择 Lodash ? Lodash 通过降低 array.number.objects.string 等等的使用难 ...

  2. Lo-Dash – 替代 Underscore 的优秀 JS 工具库

    前端开发人员大都喜欢 Underscore,它的工具函数很实用,用法简单.这里给大家推荐另外一个功能更全面的 JavaScript 工具——Lo-Dash,帮助你更好的开发网站和 Web 应用程序. ...

  3. 【翻译】在Ext JS集成第三方库

    原文地址:http://www.sencha.com/blog/integrating-ext-js-with-3rd-party-libraries/ 作者:Kevin Kazmierczak Ke ...

  4. ios开发不能不知的动态修复bug补丁第三方库JSPatch 使用学习:JSPatch导入、和使用、.js文件传输加解密

    JSPatch ios开发不能不知的动态修复bug补丁第三方库JSPatch 使用学习:JSPatch导入.和使用..js文件传输加解密 ios开发面临审核周期长,修复bug延迟等让人无奈的问题,所以 ...

  5. Underscore——JS函数库

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826065.html underscore是什么——它是一个js函数库 jQuery统一了不同浏览器之间的 ...

  6. iOS 第三方库、插件、知名博客总结

    iOS 第三方库.插件.知名博客总结 用到的组件 1.通过CocoaPods安装 项目名称 项目信息 AFNetworking 网络请求组件 FMDB 本地数据库组件 SDWebImage 多个缩略图 ...

  7. iOS非常全的第三方库

    iOS ● 非常全的三方库.插件.大牛博客等等   github排名:https://github.com/trending, github搜索:https://github.com/search. ...

  8. JS 常用库汇总收集

    本文不定期更新, 用于汇总记录一些看着 ok 的 JS 库. 库名 简介 项目地址 macy.js 仅 4 kb的 原生 流布局插件 http://macyjs.com/ Driver.js 仅 4 ...

  9. Python库,让你相见恨晚的第三方库

    环境管理 管理 Python 版本和环境的工具 p – 非常简单的交互式 python 版本管理工具.pyenv – 简单的 Python 版本管理工具.Vex – 可以在虚拟环境中执行命令.virt ...

随机推荐

  1. Hive Essential (4):DML-project,filter,join,union

    1. Project data with SELECT The most common use case for Hive is to query data in Hadoop. To achieve ...

  2. PAT 甲级 1071 Speech Patterns (25 分)(map)

    1071 Speech Patterns (25 分)   People often have a preference among synonyms of the same word. For ex ...

  3. prometheus数据格式

    注意区分以下两种“数据格式”: 1.自定义exporter的时候所需要遵循的给prometheus提供数据的数据格式: https://yunlzheng.gitbook.io/prometheus- ...

  4. easyui前台改变datagrid某单元格的值

    有时候前台完成某个操作后要修改datagrid的值, 也许这个datagrid是没有保存的, 所以要修改后才能传递到后台; 也许要其他操作过后才需请求后台; 这些情况都需要前台对datagrid的单元 ...

  5. __proto__和prototype的一些理解

    var Person = function(name) { this.name = name; } var p = new Person(); new操作符的操作是 var p = {} p.__pr ...

  6. Vue + ElementUI的电商管理系统实例03 用户列表

    1.通过路由展示用户列表页 新建user文件夹,里面新建Users.vue文件: <template> <div> <h3>用户列表组件</h3> &l ...

  7. R去掉含有NA的行

    只要数据框中含有NA的行都去掉 final[complete.cases(final),] na.omit(final) 过滤某几列 final[complete.cases(final[,5:6]) ...

  8. Redis项目实战 .net StackExchange.Redis

    StackExchange.Redis 免费.支持异步.用的最多 常用对象 源码地址:https://github.com/StackExchange/StackExchange.Redis    用 ...

  9. Object 方法的 hashCode,equals方法源码

    文章目录 hashCode方法注释 equals 方法注释 equals 方法 hashCode方法注释 Object 的 hashCode 方法,是本地方法: Returns a hash code ...

  10. 【Qt开发】第一个Qt程序Hello World!

    一:说在前头 我的第一份工作是做生产工具,当时用的MFC,IDE是VC6.0,现在想想真是古董级别,10年至今,微软也一直没有对MFC进行升级,冥冥中感觉微软自己都放弃MFC了,市场上貌似MFC的岗位 ...