我想要...

国庆假期,被朋友拉入了 MC 的世界。在一次偶然的探索中,我获得了一颗小小的"可可豆"。看着这颗普通的豆子,我心中突然涌起一个简单的愿望——做一杯热腾腾的热可可。说来有趣,作为一个胖子,现实生活中我几乎从不碰这类高热量饮品,但在这个虚拟世界里,这个想法却如此自然地冒了出来。在朋友的指导下,我开始了这场看似简单却意外复杂的"工程":搭建自动化生产线。 当我坐在屏幕前,看着这套精密运转的自动化装置时,一个念头突然闪过——我终于明白 MC 为什么如此吸引人了。 这个过程其实是一个完美的目标实现模型:我有一个原始的冲动(做热可可),游戏将这个目标自动拆解成无数个子任务(合成不同的道具),而我需要做的就是逐层深入,弄清楚每个组件的获取方法,直到追溯到最基础的原材料。这不正是我们在现实世界中解决问题的方式吗?目标 → 拆分子目标 → 持续细化 → 基础行动。 更有趣的是,完成同一个目标往往有多种路径。比如制糖需要甘蔗,我最初建了一个传统的甘蔗种植房,但效率实在太低。于是我开始研究"园艺玻璃罩"这种更高效的方案。这个学习和选择的过程,不也正是我们在现实中面对挑战时的思维模式吗——寻找更优解,不断优化方法。 通过这杯看似简单的"热可可",我意外地窥见了这个游戏建造系统的精妙之处。更重要的是,我的朋友们从未因为这只是一杯普通的热可可而阻止我的探索。在这里,没有人会说"你应该去做更重要的事",每个人都在追求自己想要的东西。 这就是"我应该要…“和"我想要…“的本质区别。 在 MC 这个"我想要"的世界里,每一个小小的成就都能带来纯粹的快乐和强烈的正反馈。而在现实这个"我应该要"的世界里,我们往往被社会期待和权威标准所驱动,做着那些"正确"但未必让自己快乐的事情。 人生何尝不是一个大型开放世界游戏?我们不应该永远困在"我应该要"的框架里。是时候重视自己的游戏体验了,是时候去构建属于自己的"我想要"的世界了。

October 10, 2025 · 1 min · Zink

记录 node/package manager 的一些细碎

yarn2 yarn2不再支持yarn global add,参考 issue。 顺便一说发现好多人还在用yarn1… volta 使用volta作为node manamger,目前存在无法使用pnpm全局安装的问题,同样可采用pnpm dlx ...的方式来解决 volta uninstall yarn失败,参考 issue1、issue2。 2025.2.17更新:已切换到 fnm 管理 node 版本,无法忍受不能使用 –global 指令,并且如果是在/node_modules/dir目录下使用 pnpm link,会自动忽略 package.json 并报错 fnm fnm和volta 用下来,个人还是感觉volta更舒适,主要还是在于volta对于node版本的切换无感知,而fnm需要手动切换版本。 volta只需要在项目中volta pin node@x.x.x就可以将版本写入package.json中,随后每次进入不同的目录都会自动切换到对应的node版本。 2025.2.17更新:官方的自动安装脚本有错误,需手动修复 FNM_PATH corepack corepack不能与volta使用,当你使用volta install node后,你的node中并没有 corepack,参考 issue1、issue2 虽然说corepack已经被视为规范,但它处于试验阶段好几年了,且node官方常年不作为…所以我还是选择先相信volta

December 2, 2024 · 1 min · Zink

6.29 思考

入职快两个月了,这段时间基本是被工作推动生活,几乎忘了自己的目标,今天更新 checklist 的时候终于有机会回过头来看了。发现这样的状态还是蛮危险的,安逸于当下的生活,对未来失去了活力。 最近又感到自己知识上的匮乏,twitter 最近的 timeline 发生了一些大事,我能感觉到这些事背后还有更深的冰山,但是我无法探究下去,甚至无法用语言对下面这座冰山进行一个粗略的描述。这使我焦虑,或许我应该调整一下生活模式:把学习新知识作为一个构建生活的方式,而不是用娱乐、工作、消遣来填满我的生活。 人还是不能被普通人叙事打倒,一定得在某些方面追求卓越(不一定是社会面的判断标准),才能让自己感觉到活着。

June 29, 2022 · 1 min · Zink

Event Loop Promise async/await 总结

同步任务 因为 JavaScript 是单线程的,所以同步任务只能在主线程上排队执行,并且只有当前一个任务完成才能执行下一个任务 当 JavaScript 运行时,每个函数的执行都会进入调用栈(Call Stack)中,当前函数执行完毕后将其移出栈,然后执行下一个函数,如果其中有非常耗时的函数执行,那么调用栈就阻塞了,后面的任务只能一直处于等待状态无法执行,且此时 UI 对面任何用户操作都不会响应,看起来就像程序崩溃了一样。 为了解决这个问题,我们有了异步任务。 异步任务 常见的异步: setTimeout() setInterval() Promise.resolve().then() fetch.then() 异步任务在执行之前不会进入调用栈,它进入事件循环队列(Event Loop Queue),当主线程执行完毕后,且异步时机到了,就会将事件循环队列中的任务推入调用栈中执行。 Event Loop Event Loop 的工作非常简单,它只是监控调用栈和回调队列(包含每个事件对应的回调函数,比如 click 的回调函数)。如果调用栈为空,Event Loop 将队列中的第一个任务移除并推送到调用栈。 从 ES6 开始,Event Loop 处理异步也分两种,在Macrotask中处理setTimeout这类的,在Microtask中处理Promise这类的。它会优先处理Microtask中的任务 browser event model Node.js 中的 Event Loop Node.js 中的 Event Loop 分为 6 个阶段,依次是: timers 定时器 这个阶段执行已被setTimeout()和setInterval()调度的回调函数 pending callbacks 待定回调 执行延迟到下一个循环迭代的I/O回调 idle, prepare Node.js 系统内部使用 poll 轮询 检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,那些由计时器和 setImmediate() 调度的之外),其余情况 node 将在适当的时候在此阻塞(等待) check 检测 setImmediate()回调函数在这里执行 close callback 关闭的回调函数 一些关闭的回调函数,如:sockt.on('close', ...) process.nextTick()的回调会在每个阶段结束之前调用。 ...

March 10, 2022 · 1 min · Zink

React 哲学

最近在看 React 的文档,因为之前有使用 Vue 的经验,所以其中的概念理解起来倒是不算难,不过 React 的文档给我的感觉并不只是教我怎么写 React,怎么使用它的语法,它更多的是在教我如何从组件的角度出发,编写一个健壮的 web app。 以前在写 Vue 组件的时候,通常是使用现有的基础组件库,然后拼装成一个 page component,所有数据都由 page component 管理,通过 props 将数据分发给子组件,但是以前并没有思考过为什么要这样做,只是因为大家都这样写代码,所以我也这样写代码。 而 React 哲学告诉了我们,在面对一份新的设计稿时,应当如何从最基本的层面去思考如何构建这个页面。 第一步:通过 UI 来划分组件 其实在设计领域,也一直在推崇组件化,即设计师在设计 UI 时,也需要将每个功能点按组件划分,并不是一味地堆叠元素。 通过单一功能原则来判断组件的分为 第二步:创建一个静态版本 这一步通俗来说应该就是切图了,通过 mock data 构建一个没有交互能力的静态版本 第三步:确定 UI state 的最小(且完整)表示 确定哪些数据是需要组件自身来更改。 通过可以从以下三步判断: 该数据是否是由父组件通过 props 传递而来的?如果是,那它应该不是 state。 该数据是否随时间的推移而保持不变?如果是,那它应该也不是 state。 这一步我的理解是,该数据是否可由组件自身的交互操作改变它 你能否根据其他 state 或 props 计算出该数据的值?如果是,那它也不是 state。 第四步:确定 state 放置的位置 假设现在拥有 parent compoent、child1 component 和 child2 component(后文简称 p、c1、c2),c2 中的数据由 p 通过 props 传递给它,c1 自身维护一份 state,但 c2 中的数据依赖 c1 的 state,那么此时应该将 c1 的 state 提升到 p 中,并通过 props 传递给 c1 ...

March 2, 2022 · 1 min · Zink