反应式编程

kriskowal/gtor

反应式宣言

嗯...但在此之前,想先看看防抖节流,锁,事务一致性,以及js 的 Promise。

stupid!

debounce & throttle

react 文档里有说过,不要信任用户的操作,用户根本不知道自己的操作到底在干嘛也不需要去知道,收到的所有的操作都要加一个 handler, debounce & throttle 就是两种最常见的 handler。

difference-between-throttling-and-debouncing-a-function

debounce 的意思是,如果用户在短时间内多次触发了事件,那么只有最后一次事件会被处理,前面的事件都会被忽略。

常见场景是,用户在输入框中输入内容,如果每次输入都触发事件,那么就会导致事件处理函数被频繁调用,这样会影响性能进而可能影响体验,所以一般会使用 debounce 来处理这种场景,只有用户输入完毕后,才会触发事件。不仅仅是文字输入,鼠标移动,窗口大小改变等等都可以使用 debounce 来处理一下。

throttle 的意思是,如果用户在短时间内多次触发了事件,那么只有每隔一段时间的事件会被处理,前面的事件都会被忽略。

这里,主要,更多的保护的可能不是用户体验了,这里更多的是保护服务器,主要是在用户明确的点击、提交行为时,防止用户在短时间内多次点击、提交,导致服务器压力过大,或者重复提交数据错误一类的问题。


redis 实现 throttle,节流。

keys *
set key
get key
del key [key ...]
expire key seconds ttl key

mset/mget/msetnx/mgetnx
bitop/bitcount/bitpos/bitfield // 位操作, 有人玩的特别花

hset/hget/hdel/hexists/hgetall/hkeys/hvals/hincrby/hincrbyfloat/hstrlen/hscan // hash
lpush/lpop/rpush/rpop/lrange/ltrim/lindex/lset/lrem/linsert/llen/lpushx/rpushx/lpop/rpop/lpop/rpoplpush/blpop/brpop/brpoplpush // list

sadd/srem/sismember/smembers // 集合
zadd/zrem/zrange/zrangebyscore/zrevrangebyscore/zrank/zrevrank/zscore/zcard/zcount/zscan/zremrangebyrank/zremrangebyscore // 有序集合,为什么‘z’开头?redis开发者也觉得牵强。。


如要限制每分钟每个用户最多只能访问100个页面,思路是对每个用户使用一个名为 rate.limiting:用户 IP的字符串类型键,每次用户访问则使用 INCR命令递增该键的键值,如果递增后的值是1(第一次访问页面),则同时还要设置该键的过期时间为1分钟。这样每次用户访问页面时都读取该键的键值,如果超过了100就表明该用户的访问频率超过了限制,需要提示用户稍后访问。该键每分钟会自动被删除,所以下一分钟用户的访问次数又会重新计算,也就达到了限制访问频率的目的。

这里存在一个不太明显的问题:假如程序执行了但没执行完,中途突然因为某种原因退出了,没能够为该键设置过期时间,那么该键会永久存在,导致使用对应的IP的用户在管理员手动删除该键前最多只能访问100次博客,这是一个很严重的问题。为了保证建立键和为键设置过期时间一起执行,可以使用上节学习的事务功能.

事实上,仍然有个问题:如果一个用户在一分钟的第一秒访问了一次博客,在同一分钟的最后一秒访问了9次,又在下一分钟的第一秒访问了10次,这样的访问是可以通过现在的访问频率限制的,但实际上该用户在2秒内访问了19次博客,这与每个用户每分钟只能访问10次的限制差距较大。尽管这种情况比较极端,但是在一些场合中还是需要粒度更小的控制方案。如果要精确地保证每分钟最多访问10次,需要记录下用户每次访问的时间。因此对每个用户,我们使用一个列表类型的键来记录他最近10次访问博客的时间。一旦键中的元素超过 10 个,就判断时间最早的元素距现在的时间是否小于 1分钟。如果是则表示用户最近1分钟的访问次数超过了10次;如果不是就将现在的时间加入到列表中,同时把最早的元素删除。

2333... 真是麻烦又折磨,书的作者最后也推荐使用另外的脚本来实现节流。

那,来个 js 版本的。

JS 有两个时间的函数 setTimeout 是到了之后调一次也只调一次,setInterval 是每隔一段时间调用一次一直搞下去。
但 debounce 和 throttle 都是在一定条件下调用一次,(不停的操作是用户已经在做的了)所以,这里,我们用 setTimeout 来做这两个函数。

function debounce(fn, delay) {
  let timer = null;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, arguments);
    }, delay);
  }
}
function throttle(fn, delay) {
  let timer = null;
  return function() {
    if (!timer) {
      timer = setTimeout(() => {
        fn.apply(this, arguments);
        timer = null;
      }, delay);
    }
  }
}

transaction & lock

事务的ACID,原子性,一致性,隔离性,持久性。 如果要挑重要的,那就是原子与隔离。——原子性表示不可分;隔离性类似解耦。

Promise

callback


我还是不想进入正题

通信,信号处理...

socket && publish & subscribe && message queue

cluster

Reactivity

functional programming ? reactive programming??

....RxJS


花木瑞指南大约 8 分钟
服务端

服务端的知识可能在这里
SSR-SSG
可能有说过一些

JavaJavaScript 中,也稍微提了些编程语言和生态相关的东西,但,我今天看到了本书,是, ruby 的作者写的一本书。
语言是重要的,程序员的体验是重要的...,在设计模式那一节,《设计模式》并不是那些模式的开山鼻祖,许多早就广泛应用了,那本书做的更多的是归类总结,并且给它们一个名字,对的,名字。有了名字之后,才可能会有之后的共识... 神话故事里因为不同语言而放弃修塔... 某些时候也很真实。
语言是重要的...我现在使用的各种工具是,写下的文字是,它们本身可能确实什么都不是,但我好像能看到在这上面的累积,数不清的人的思考,与共识。


花木瑞指南大约 1 分钟
NodeJS

在弄完 联网小游戏 之后... 算是了了一个心愿。 想要搞搞后端然后凑一个像样的小玩意,也就,顺着来好好看看 NodeJS 吧。

node 基础的 http 模块 => express / fastify / koa => nest / egg / strapi

他们算是,三层。

找到个 nodepress ,弄过来,搞一搞。


花木瑞指南小于 1 分钟