jump-and-jump
jump-and-jump
笔者曾经开发过一个数据分享类的小程序,分享逻辑上类似于百度网盘。当前数据可以由被分享者加工然后继续分享(可以控制数据的过期时间、是否可以加工数据以及继续分享)。 分享的数据是一个深度嵌套的 json 对象。在用户读取分享数据时存入小程序云数据库中(分享的数据和业务数据有差异,没使用业务服务器进行维护)。如果拿到数据就直接存储的话,很快云数据库就会变得很大,其次我们也没办法分析各项和检索各项子数据给予分享者。 这时候需要进行数据转换以便拆分和维护。我们可以使用 [redux](http://cn.redux.js.org/) 作者 Dan Abramov 编写的 [normalizr](https://github.com/paularmstrong/normalizr) 来处理数据。 normalizr 创立的初衷是处理深层,复杂的嵌套的对象。 ## 如何使用 稍微修改一下官方的例子,假定获取到如下书籍的数据: ```js { id: "1", title: "JavaScript 从入门到放弃", // 作者 author: { id: "1",...
对于很多项目来说,某些配置项或查询条件是必需的。当用户丢失配置数据或项目下线配置项,都会导致项目发生错误而造成不可用的问题,这时候,开发需要提供一些兜底策略,如当前列表数据查询不到时默认使用第一项。而这些东西写起来又很麻烦,所以这里进行了一次封装,代码如下: ```ts interface EnsureGetValFromListParams { /** 列表数据 **/ items: ItemType[] value?: ValueType | undefined /** 列表中数据值的提取方法 **/ getVal?: (item: ItemType) => ValueType /** 查询不到数据时候返回值的位置 **/ pos?: 'frist' | 'last' }...
绝大部分情况,网络请求都是先请求先响应。但是某些情况下,由于未知的一些问题,可能会导致先请求的 api 后返回。最简单的解决方案就是添加 loading 状态,在所有请求都完成后才能进行下一次请求。 但不是所有的业务都可以采用这种方式。这时候开发者就需要对其进行处理以避免渲染错误数据。 ## 使用“版本号” 我们可以使用版本号来决策业务处理以及数据渲染: ```ts const invariant = (condition: boolean, errorMsg: string) => { if (condition) { throw new Error(errorMsg) } } let versionForXXXQuery =...
对于企业应用来说,完全不涉及到并发的问题,基本是不可能的。因为对于一个应用中很多的事情都是同时进行的。并发可能发生在数据获取,服务调用乃至于用户交互中。并发问题有两个重要的解决方案,一个是隔离,另一个是不变性。 并发问题会发生在多个执行单元同时访问同一资源的时候,此时,一个好的方法就是分好“蛋糕”,让每一个执行单元都能访问到各自的资源。好的并发设计就是:找到创建好隔离区的办法,然后通过分析工作流让隔离区能够完成尽可能多的任务。 在共享数据可以改变的情况下,并发问题就有可能发生。从实际的场景出发,同时有两个客户询问两位服务员是否还有某一货品时,两位服务员各自去查看了一下系统并回复客户还有一份,两位客户中一定有一位会失望。那么这件事情的解决方案就是添加隔离区(购物车),服务员把当前货品放入客户的购物车成功后告知用户,然后失败的一方就可以告知用户货品已经销售一空。虽然存在已购用户退货的可能,但无疑比前一结果要好太多。这也就是下文中所说的悲观锁。 下面我们开始介绍两种并发控制策略: ## 乐观和悲观并发控制 在某个系统中,同时有两个企业员工 A 和 B 想要编辑同一个用户信息。此时 A 和 B 都获取到了用户的信息数据。然后他们两个进行了修改,A 员工先完成了操作并且进行了提交。然后 B 员工完成了操作也进行了提交。此时系统中的这个用户信息只保留了 B 提供的数据,而丢弃了 A 员工的数据。这可能会造成一些难以预料的问题,甚至有可能导致他们丢掉工作。虽然可以通过操作日志来追溯到是哪个员工操作了数据,但这个信息没有任何意义,因为系统并没有让任何员工得知修改这一情况。 当一些可变数据无法隔离时候,我们可以用两种不同的控制策略:乐观锁策略和悲观锁策略。乐观锁用于冲突检测,悲观锁用于冲突避免。 悲观者策略非常简单,当 A 用户获取到用户信息时系统把当前用户信息给锁定,然后 B 用户在获取用户信息时就会被告知别人正在编辑。等到 A 员工进行了提交,系统才允许...
队列,在数据结构中是一种线性表,其特性为必须从一端插入,然后从另一端删除数据。但笔者今天重点不是如何实现该数据结构,我们可以看一看如何借助队列管理复杂的任务。 队列在实际开发中应用的场景非常广泛。因为在一个复杂的系统中,总是会有一些非常耗时的处理。在这种时候开发者不能要求系统提供实时处理、实时响应的能力。这时候我们就可以通过队列来解决此类问题。 开发者可以不停地往队列塞入数据,并为其生成唯一值(进行跟踪),同时根据当前系统的处理能力不断的从队列取出数据进行业务处理,以此来减轻在同一时间内进行大量复杂业务处理,以便增强系统的处理能力。 服务端通常可以借助队列来进行异步处理、系统解耦、数据同步以及流量削峰。 如果需求较为简单,开发者可以直接借助数组来进行处理。对于较为复杂的需求,可以使用 [better-queue](https://github.com/diamondio/better-queue) 来解决问题。 better-queue 进一步扩展了队列,让其有很多好用的功能。诸如: - 并行化处理 - 持久(和可扩展)存储 - 批处理 - 优先队列 - 合并、过滤任务 - 任务统计 ## 使用方法 让我们开始看一看 better-queue 如何使用。 ### 代码风格 ```ts import...
# 前端 api 请求缓存方案 在开发 web 应用程序时,性能都是必不可少的话题。对于webpack打包的单页面应用程序而言,我们可以采用很多方式来对性能进行优化,比方说 tree-shaking、模块懒加载、利用 extrens 网络cdn 加速这些常规的优化。甚至在vue-cli 项目中我们可以使用 --modern 指令生成新旧两份浏览器代码来对程序进行优化。 而事实上,缓存一定是提升web应用程序有效方法之一,尤其是用户受限于网速的情况下。提升系统的响应能力,降低网络的消耗。当然,内容越接近于用户,则缓存的速度就会越快,缓存的有效性则会越高。 以客户端而言,我们有很多缓存数据与资源的方法,例如 标准的浏览器缓存 以及 目前火热的 Service worker。但是,他们更适合静态内容的缓存。例如 html,js,css以及图片等文件。而缓存系统数据,我采用另外的方案。 那我现在就对我应用到项目中的各种 api 请求缓存方案,从简单到复杂依次介绍一下。 ## 方案一 数据缓存 简单的 数据...
懒加载 惰性求职 https://segmentfault.com/a/1190000000358463 基于业务来决定当前抉择
上周花了 3 天的时间和老大一起重构了一下小程序的样式开发,虽然说在开发的过程中遇到了一些问题,但是最终减少了不少样式代码,同时功能上也更加强大。进一步来说,如果在后面我们的小程序用户想要自己定制化主题,也可以很快的实现。 ## 全局样式开发 之前的小程序开发中,我们全方面使用了 [Component](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/component.html) 构造小程序组件以及页面(页面也可以使用 Component 构造器来编写)。当然一方面是因为小程序 Component 的开发体验非常好,拥有类似于 Vue mixin, watch 的 [behaviors](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/behaviors.html) 和 [observers](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/observer.html),比 Page 构造器强大了很多。另一方面,对于业务较重的小程序来说, Component 也有性能优势。可以参照 [滴滴开源小程序框架Mpx](https://juejin.im/post/5c0f693ef265da61542d78c6) 中的 *Page与Component setData性能对照*。 在开发过程中,有很多样式是可以复用的。如果在之前开发中经常使用 [Bootstrap](https://getbootstrap.com/) 之类的...