首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

WEB-WORKER进阶学习(二)

由于JS单线程模型的原因,虽然可以通过异步来处理请求。但是最终还是需要由主线成处理 出于希望将渲染 / (请求、计算) 解耦的想法,所以对现在由axios构建的api请求层做改造,所有的数据请求交予web-work处理。达到渲染与请求分开的目的 问题 同时存在多少个Worker比较合适 ? 理论上worker没有上限,开启多少个都可以,根据实际情况即可。不建议按照CPU(navigator.hardwareConcurrency)核心数开启对应的数量 像目前做的请求/渲染分离就是开启4个作为守护线程。因为除了IE6,7最少支持4个并发请求 多个Worker如何协同工作 ? 需要考虑开启多个worker的统一调配的问题,与负载均衡的问题。 开启的worker可以通过数组存储 负载均衡可以使用轮询,最有可用等算法来处理 消息该如何处理 ? 与axios不同的是,worker处理请求跨越不同的线程,真正的实现异步的请求。那如何保证正确的触发回调 内部通过Promise构建,返回调用者Promise对象,同时为任务分配唯一ID。将任务ID, resolve,reject 同时存储记录 worker将返回数据/异常与接受到的任务ID一并打包返回 通过任务ID将任务从任务池中pop出,执行对应的回调 请求使用什么技术? 仍然使用axios还是fetch ? 这点其实比较纠结 axios使用方便 但是不使用axios可以缩减压缩包体积 如果是项目改造需要将axios的格式与fetch的api格式做转换处理 最终选用fetch, 在内部实现时,增加拦截器对数据做处理。 另外考虑的一点是, fetch脱离了xhr的。理论上性能更好,但是也有缺点 fetch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理 fetch默认不会带cookie,需要添加配置项 fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了量的浪费 fetch没有办法原生监测请求的进度,而XHR可以 全局配置如何处理,例如请求头? 通过拦截器前置处理 跨域的问题 ? 不建议使用jsonp, 可以增加cors头或者增加一个node做中转 如何将worker的代码混淆压缩? 通过 对web-worker做处理,配置如下 // 整合worker-loader,基于vue-cli3 config.module .rule('worker') .test(/\.worker\.js$/) .use('worker-loader') .loader('worker-loader') .end() config.module.rule('js').exclude.add(/\.worker\.js$/) webpack外链(未测试) 实现 整体构思将分为两块 线程组 工作组内部持有所有活动work的实例,提供消息转发,均衡算法支持,回调机制实现,内部包含 interceptor 拦截器 参考axios的前后置拦截机制,提供默认的请求、相应的处理并对外暴露 export const interceptors = { // 前置适配转换数据类型 transfer(config) { return { url: `${window.location.origin}${process.env.VUE_APP_BASE_API}${config.url}${config.params ? '?' + param(config.params) : ''}`, options: { body: config.data ? JSON.stringify(config.data) : undefined, cache: config.cache, headers: config.headers || {}, method: config.method || 'GET' } } }, // 请求过滤 request(config) { if (store.getters.token) { config.options.headers['Auth'] = getToken() } return config }, // 响应过滤 async response(res) { return res } } balance 负载均衡 内部实现负载均衡的实现 const balance = (function() { let index = 0 /** 均衡算法 */ const BALANCE_ALGORITHM = { /** 轮询下标 */ ROUND_ROBIN() { const next = workers[index % workers.length] index++ return next } } const tasks = {} const addTask = (option, resolve, reject) => { const id = uuid() option.id = id tasks[id] = { resolve: resolve, reject: reject } } return { next() { return BALANCE_ALGORITHM.ROUND_ROBIN() }, postMessage(option, resolve, reject) { addTask(option, resolve, reject) this.next().postMessage(option) }, popTask(id) { const task = tasks[id] delete task[id] return task } } })() workers worker线成组,持有对应实例 const workers = new Array(4) for (let i = 0; i < workers.length; i++) { const worker = new Worker() worker.onmessage = receive workers[i] = worker } 工作组 工作组内部实现队列机制,接受到的任务逐一消费回复,通过队列机制防止高并发的请求峰值,通过合理的机制对请求削峰,并且浏览器对单域请求存在上限(以Chrome为例,上限为6)。所以内部实际是一个状态机,其内部包含: queue 请求任务队列 const queue = [] state 当前运行状态, 默认空闲 /** 运行中 */ const RUNNING = 'RUNNING' /** 空闲 */ const IDLE = 'IDLE' /** 当前状态 */ let state = IDLE request 请求函数 /** * 执行请求 * 通过fetch发送请求,将反馈发送到主线程 * 结束后检查队列 * @param event event main-thread message */ const request = (event) => { state = RUNNING const { data } = event fetch(data.url, data.options) .then(response => response.json()) .then(json => { postMessage({ success: true, response: json, id: data.id }) }) .catch(reason => { postMessage({ error: true, message: reason.message, id: data.id }) }) .finally(() => { const next = queue.pop() if (next) { request(next) } else { state = IDLE } }) } 不足 超时等问题如何处理? 文件上传如何处理? 增加轮询之外的负载策略?

优秀的个人博客,低调大师

前端学习笔记(6) - JavaScript数组

在最新的TypeScript 3.6中实现了更准确的数组扩展。借此机会聊一下我对js中数组的一点理解。 使用Array()初始化数组 先来看一下下面的两行代码 1 in [undefined, undefined, undefined] // true 1 in Array(3) // false 再看一下接下来代码 let arr=new Array(3).map(()=>{return 3}) console.log(arr) //(3)[empty × 3] 可见使用无论使用Array方法还是使用Array构造器所生成的数组均为没有索引与元素单存在length属性的空数组。(参数为单个非负整数时)map方法对于没有赋值或者被delete删除的索引不会调用 初始化数组 以下三种方法都可以得到一个[undefined, undefined, undefined]数组 Array(...Array(3)) Array.apply(null,Array(3)) Array.apply(null,{length:3}) 第一种第二种方法比较好理解,但是第三种apply方法的第二个参数为数组为什么传入一个对象同样可以执行。据我测试后发现ie8及以下版本中会直接报错,chrome、firefox、edge、ie9-11中可以执行。目前大部分浏览器都支持apply传入一个类数组对象。有些文章中称是因为{length:3}为一个可迭代方法,实际上是错误的说法,对象是否可迭代实际上是由对象及其原型链上是否存在[Symbol.iterator]方法决定的。调用该方法可以得到一个对象的迭代器,调用对象的keys方法也可以得到一个相同的迭代器 [1,2,3][Symbol.iterator]() [1,2,3].keys() 另外enumerable为false的属性无法被keys、for in 、entries枚举。 let tempArr=[1,2,3] Object.defineProperty(tempArr,'0',{enumerable:false}) for(let i in tempArr){ console.log(tempArr[i]) } //2 3 Object.keys(tempArr) //(2)["1", "2"] Object.entries(tempArr) //(2) [["1", 2],["2", 3]]

优秀的个人博客,低调大师

python算法学习笔记1

python中array 是一整块单一连续的内存区域,根据索引值访问的话可以直接计算出目标元素在内存中的位置,对于链表要从头开始遍历链表插入代价小,数值插入代价大,要移动右边所有的元素这边的数组指动态数组复杂度O 构建排序算法之前先对序列进行检查,如果目标已经排过序则直接返回 def sort_w_check(): n=len(seq) for i in range(n-1): if seq[i] >seq[i+1]: break else: return .... 排序的三种情况:1.最好情况,已经排好序,线性时间2.最坏情况3.平均情况,期望时间算法评估:用timeit模块 import timeit t1=timeit.timeit("x=2+2") print(t1) t2=timeit.timeit("x=sum(range(10))") print(t2) 计算时间,但对于多次迭代时timeit会通过多次运行相关代码的方式来提高计时精度图结构:图的要点主要包括: 散列(hashing)可以通过python中的hash函数提供 print(hash("hello,world!")) print(hash("Hello,world!")) python中字典类型dict就是常说的散列表,集合类型也是通过这种机制完成的,对于散列的访问平局时间为O(1),最坏为O(n)邻接列表及类似的结构示意图 示意图转换为邻接集表示方法 a,b,c,d,e,f,g,h=range(8) N=[ {b,c,d,e,f}, {c,e}, {d}, {e}, {f}, {c,g,h}, {f,h}, {f,g} ] 加权的邻接列表 a,b,c,d,e,f,g,h=range(8) N=[ {b:2,c:1,d:3,e:9,f:4}, {c:4,e:3}, {d:8}, {e:7}, {f:5}, {c:2,g:2,h:2}, {f:1,h:6}, {f:9,g:8} ] 邻接集的字典表示法: N={ 'a':set('bcdef'), 'b':set('ce'), 'c':set('d'), 'e':set('e'), 'f':set('cgh'), 'g':set('fh'), 'h':set('fg') } 树二叉树 class Tree(object): """docstring for Tree""" def __init__(self, left,right): self.left=left self.right=right t=Tree(Tree("a","b"),Tree("c","d")) print(t.right.left) 多路搜索树 class True: def __init__(self,kids,next=None): self.kids=self.val=kids self.next=next t=Tree(Tree("a",Tree("b",Tree("c",Tree("d"))))) print(t.kids.next.next.val) 隐性平方级操作例子 import time from random import randrange L=[randrange(10000) for i in range(1000)] t1=time.time() print(42 in L) t2=time.time() print(t2-t1) S=set(L) t3=time.time() print(42 in S) t4=time.time() print(t4-t3) 对list的搜索是线性数量级的,set的搜索是常数级的

优秀的个人博客,低调大师

Elasticsearch学习笔记(一)之what?

一句话介绍 Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎,能够解决不断涌现出的各种用例。作为 Elastic Stack 的核心,它集中存储您的数据,帮助您发现意料之中以及意料之外的情况。---摘自官方文档 他的父亲 Elasticsearch 的前世或者父亲应该可以说是Lucene。它是基于Java开发并且开源,目前被认为性能最好的全文检索引擎,但是它并不能直接拿来用或是对外提供服务。它本质上只是一个工具包,需要对它进行二次封装。目前基于Lucene组件的全文搜索应用有两个:Solr和Elasticsearch 。 他的兄弟 他的老大哥solr也是基于Lucene,2007发布第一版,作为企业级应用的全文检索服务,solr曾经也是风云一时。2010年,一个程序员为让他的妻子能够方便检索菜谱而开发的全文搜索服务横空出世,顺应大数据时代的潮流,他以其分布式,大数据量方面的处理优势迅速占领一席之位。Elasticsearch发展至今风头甚至可以说已经盖过了他曾经的老大哥solr。 兄弟PK 那么,到底是选择 Solr 还是 Elasticsearch?有时很难找到明确的答案。无论您选择 Solr 还是 Elasticsearch,首先需要了解正确的用例和未来需求,总结它们的每个属性。 记住下面这些要点: 由于易于使用,Elasticsearch 在新开发者中更受欢迎。但是,如果您已经习惯了与 Solr 合作,请继续使用它,因为迁移到 Elasticsearch 没有特定的优势。如果除了搜索文本之外还需要它来处理分析查询,Elasticsearch 是更好的选择。如果需要分布式索引,则需要选择 Elasticsearch。对于需要良好可伸缩性和性能的云和分布式环境,Elasticsearch 是更好的选择。两者都有良好的商业支持(咨询,生产支持,整合等)。两者都有很好的操作工具,尽管 Elasticsearch 因其易于使用的 API 而更多地吸引了 DevOps 人群,因此可以围绕它创建一个更加生动的工具生态系统。Elasticsearch 在开源日志管理用例中占据主导地位,许多组织在 Elasticsearch 中索引它们的日志以使其可搜索。虽然 Solr 现在也可以用于此目的,但它只是错过了这一想法。Solr 仍然更加面向文本搜索。另一方面,Elasticsearch 通常用于过滤和分组,分析查询工作负载,而不一定是文本搜索。Elasticsearch 开发人员在 Lucene 和 Elasticsearch 级别上投入了大量精力使此类查询更高效(降低内存占用和 CPU 使用)。因此,对于不仅需要进行文本搜索,而且需要复杂的搜索时间聚合的应用程序,Elasticsearch 是一个更好的选择。Elasticsearch 更容易上手,一个下载和一个命令就可以启动一切。Solr 传统上需要更多的工作和知识,但 Solr 最近在消除这一点上取得了巨大的进步,现在只需努力改变它的声誉。在性能方面,它们大致相同。我说“大致”,因为没有人做过全面和无偏见的基准测试。对于 95% 的用例,任何一种选择在性能方面都会很好,剩下的 5% 需要用它们的特定数据和特定的访问模式来测试这两种解决方案。从操作上讲,Elasticsearch 使用起来比较简单,它只有一个进程。Solr 在其类似 Elasticsearch 的完全分布式部署模式 SolrCloud 中依赖于 Apache ZooKeeper,ZooKeeper 是超级成熟,超级广泛使用等等,但它仍然是另一个活跃的部分。也就是说,如果您使用的是 Hadoop,HBase,Spark,Kafka 或其他一些较新的分布式软件,您可能已经在组织的某个地方运行 ZooKeeper。虽然 Elasticsearch 内置了类似 ZooKeeper 的组件 Xen,但 ZooKeeper 可以更好地防止有时在 Elasticsearch 集群中出现的可怕的裂脑问题。公平地说,Elasticsearch 开发人员已经意识到这个问题,并致力于改进 Elasticsearch 的这个方面。如果您喜欢监控和指标,那么使用 Elasticsearch,您将会进入天堂。这个东西比新年前夜在时代广场可以挤压的人有更多的指标!Solr 暴露了关键指标,但远不及 Elasticsearch 那么多。总之,两者都是功能丰富的搜索引擎,只要设计和实现得当,它们或多或少都能提供相同的性能。

优秀的个人博客,低调大师

Android底层学习之Linux基础

1、Linux系统是一种类UNIX的操作系统,开源 2、基本命令 2.1 打开终端 Ctrl+Alt+T,或者按住Alt键,然后在光标提示处输入terminal,按回车键即可 2.2 目录操作 cd dir:change directory 切换、进入目录 pwd:查看当前所在目录 cd -:对已切换过的目录进行恢复操作,即返回到切换前目录 cd ..:切换到包含当前目录的上层目录 ls: 显示目录内容 2.3 文件操作 touch file:创建一个文件 mkdir dir:创建一个目录 rm file: 删除一个文件 rm -r dir:删除一个目录 rmdir: 删除一个目录 cp file file_copy:复制文件 mv file file_move:移动文件 find / -name filename:查找文件,find可能因用户权限出现permission denied无法查到到查找出来文件 find ./ -name 'filename' awk: 查找如在文件中查找 awk '/set/' vivado.log 打印出vivado.log文件中所包含set的行的内容。 vim使用:linux上文件本机工具,可通过sudo apt-get install vim安装,新建个文件myfile,使用vim myfile后按回车进入编辑模式,在编辑器中输入i或者a进入编辑模式,屏幕左下角有INSERT提示即表示可编辑 3、shell脚本 同windows中bat脚本一样,shell脚本是将一系列命令写到一个文件中,并赋予这个文件可执行的权限,可执行权限不能执行,则试试使用: chmod a+x myfile 4、Linux源码与Android源码介绍

优秀的个人博客,低调大师

python模块学习之glob模块

glob模块 功能描述:glob模块可以使用Unix shell风格的通配符匹配符合特定格式的文件和文件夹,跟windows的文件搜索功能差不多。glob模块并非调用一个子shell实现搜索功能,而是在内部调用了os.listdir()和fnmatch.fnmatch()。查看我之前写的fnmatch。 glob模块共包含以下3个函数:glob,isglob和escape。 glob(pathname, recursive=False) 第一个参数为需要匹配的字符串.(尽量在字符串前加r) 第二个参数代表递归调用,与特殊通配符“**”一同使用,默认为False。 路径格式可以是绝对路径 /usr/src/Python-1.5/Makefile ,也可以是相对路径../../Tools//.gif。 在3.5版本之后,glob函数支持一个特殊的通配符“**”,该通配符可以匹配指定路径里所有文件和目录,包括子目录里的所有文件和目录。使用这个通配符必须加上recursive=True参数。 (在有复杂目录结构的情况下使用该通配符可能会导致性能下降,拖累整个程序的运行,需谨慎使用!) 例如,目录中包含文件: 1.gif, 2.txt, card.gif里面含有子目录sub,sub目录里含有3.txt. >>>importglob>>>glob.glob('./[0-9].*') ['./1.gif','./2.txt']>>>glob.glob('*.gif') ['1.gif','card.gif']>>>glob.glob('?.gif') ['1.gif']>>>glob.glob('**/*.txt',recursive=True) ['2.txt','sub/3.txt']>>>glob.glob('./**/',recursive=True) ['./','./sub/'] 需要注意的是如果,文件名的前面含有点像这样,card.gif 和.card.gif,需要下面这样的方式处理通配符前加. >>>importglob>>>glob.glob('*.gif') ['card.gif']>>>glob.glob('.*.gif') ['.card.gif'] iglob(pathname, recursive=False) 参数与glob()一致。 返回一个迭代器,遍历该迭代器的结果和glob()的返回结果一致。 escape(pathname) 转义所有的特殊字符('?','*'和'['])。如果您想匹配任意可能包含特殊字符的字符串,这将非常有用。驱动器/ UNC共享点中的特殊字符不会转义,例如在Windows系统上 escape('//?/c:/Quo vadis?.txt') 将返回 '//?/c:/Quo vadis[?].txt'。但是这些非法字符是无法创建文件的所以一般也就用来测试用了。

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

用户登录
用户注册