Generator 简介
Generator 定义
Generator 是隐藏类 Iterator 的子类,Generator 对象是一个 JavaScript 的标准内置对象,它由生成器函数返回并且它符合可迭代协议和迭代器协议
生成器函数 形如 function* name() {},它内部可以包含 yield 表达式,具体功能下文再述
可迭代协议:简单说就是一个对象实现了 [Symbol.iterator]() 方法,这个方法无参,返回一个符合迭代器协议的对象
迭代器协议:定义了产生一系列值(无论是有限个还是无限个)的标准方式,当值为有限个时,所有的值都被迭代完毕后,则会返回一个默认返回值。最简的迭代器对象必须实现 next() 方法,该方法无参或接受一个参数,返回一个符合 IteratorResult 接口的对象。IteratorResult 简单地描述一下就是:
1234interface IteratorResult { done?: boolean; value?: any;}
其中 done 标识是否完成了迭代
写一个简单的符合可迭代协议和迭代器协议的对 ...
一步一步手写 Promise
一步一步手写 Promise
根据 Promises/A+ 规范实现 Promise
Promise/A+ 规范
Promises/A+ 规范(以下简称规范)可以在 Promises/A+ 查看,需要中文可以选择 AI 翻译或者 Promise/A+ 规范
简单来说,符合 Promises/A+ 规范的 promise(以下简称 promise )表示异步操作的最终结果,其应该是一个具有 then 方法的对象或者函数,该 promise 的 then 方法的行为符合规范。promise 必须处于 pending、fulfilled、rejected 三种状态之一,且其状态只允许由 pending 转换为其他两种状态——即其他两种状态不允许改变。当处于 fulfilled 状态时,promise 具有一个不可修改的值,表示异步处理的结果值;当处于 rejected 状态时,promise 具有一个不可修改的拒因(reason),表示异步处理被拒绝(或者说失败)的原因
构造
Promise 类基本骨架增加状态、最终值和拒因回调方法实现修改 promise 状态的方法按照 ES6 中使用 ...
告许仙词
告许仙词 皓皓白鳞,可曾识,伊人模样。漫漫洪水,岂可知,情意绵长。佛法无边,佛不言,执念为何。人间冷暖,人总叹,轮回由我。浮生自非空度日,莫负卿卿相伴老。玉簪绿萧是信物,来生在世认今朝。金山有令金光落,灵魄尚存灵阻魔。纵使雷峰塔下镇,拾阶扫尘心未隔。
JS 定时器拾遗
JS 定时器拾遗
今天看 JS 定时器定义的时候,发现了两个被我遗漏的点:
HTML 标准 提到,5 层定时器嵌套后最小间隔不能小于 4ms
Timers can be nested; after five such nested timers, however, the interval is forced to be at least four milliseconds.
setTimeout() 方法不只接收两个参数,而是从第三个参数开始的所有其他参数都会被传递给定时器会执行的函数,参见 setTimeout MDN
12345678setTimeout(code)setTimeout(code, delay)setTimeout(functionRef)setTimeout(functionRef, delay)setTimeout(functionRef, delay, param1)setTimeout(functionRef, delay, param1, param2)setTimeout(functionRef, delay, param1, param2 ...
JS 并发调度器
JS 并发调度器
浏览器的并发连接数量是有限的,对于 chrome,一般是 6 个。那么对于瞬时大量请求发送的场景,如果不加管控,那么有些排队靠后的请求,很可能在等待到浏览器调度前,就耗尽自己的时间限制,从而自我取消。针对这个问题,可以设计实现一个并发调度器,将并发请求“缓存”起来,控制并发数,从而避免请求在浏览器排队时超时
代码如下:
1234567891011121314151617181920212223242526272829const LimitConcurrentScheduler = function (concurrent = 5) { this.concurrent = concurrent; this.pendingRequests = 0; this.queue = [];};LimitConcurrentScheduler.prototype.dequeue = function () { while (this.pendingRequests < this.concurrent && this.que ...
基于acme的自动重新获取ssl证书脚本的修正脚本
基于acme的自动重新获取ssl证书脚本的修正脚本
acme 是一个很棒的 let’s encrypt 的客户端
但是,当本地的 nginx 设置了强制跳转 https 时,脚本会在验证域名的时候失败。为解决这样的问题,我写了一个新的脚本修正这个问题
123456789101112131415161718list="example.com another.example.com"for i in $list; do mv "/etc/nginx/conf.d/"$i".conf" "/etc/nginx/conf.d/"$i".conf.bak";cp "/etc/nginx/conf.d/"$i".conf.pre" "/etc/nginx/conf.d/"$i".conf";doneservice nginx reload/root/.acme.sh/acme.sh --cron --home &q ...
53.最大子数组和
53.最大子数组和
题目
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组是数组中的一个连续部分。
示例 1:
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入: nums = [1]
输出: 1
示例 3:
输入: nums = [5,4,-1,7,8]
输出: 23
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
**进阶:**如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。
思路
实话说,我费了老大的功夫最后也没能通过所有的用例,所以在此记录一下。
错误解法
一开始我想到的是,通过两端删减元素的方法,一步步算出中间遇到的所有可能产生更大和的数组,从而完成题解。讲道理这个思路理论上可行,但是实际执行起来有很多问题。
首先,当数组的首尾两端存在一个更小的负值的时候,删除它会让数组的和变大 ...
40.组合总和 II
40 组合总和 II
题目
给定一个候选人编号的集合 candidates 和一个目标数 target,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用 一次。
注意: 解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]
提示:
1 <= candidates.length <= 100
1 <= candidates[i] <= 50
1 <= target <= 30
思路
这一题很像三数之和的一般化。三数之和,可以通过双指针完成,但这里的一个有效解的长度是未知的,意味着并不能固定指针个数,而要动态增添指针。
第一眼的思路
我第一遍写,与前一 ...
31.下一个排列
31. 下一个排列
题目
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。
整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。
给你一个整数数组 nums ,找出 nums 的下一个排列。
必须 原地 修改,只允许使用额外常数空间。
示例 1:
输入: nums = [1,2,3]
输出: [1,3,2]
示例 2:
输入: nums = [3 ...
华胥记谈:农家楼馆杀人事件
在一个寂静的夜晚,整个小镇突然陷入了一片黑暗,停电让一切都变得格外诡异。项清、秦晴以及其他众人正身处一乡间小酒馆中,他们在这突如其来的黑暗中显得惊慌失措。项清紧紧拉着秦晴的手,试图在黑暗中找到一丝安全感,众人的目光中都充满了惶恐和不安。
这时,三楼突然传来一阵令人心悸的塌陷声,在寂静的环境中显得格外清晰。这突如其来的声响让众人的神经瞬间紧绷到了极点,大家面面相觑,不知道接下来会发生什么可怕的事情。而在这慌乱之中,都奕却表现得异常冷静,他的眼神中似乎隐藏着什么不为人知的秘密,这一异常的表现引起了项清的怀疑。
项清心中暗自揣测着都奕的异常表现,而此时大家在恐惧的驱使下,开始摸索着往楼梯口的方向走去。
当他们终于艰难地到达楼梯口时,一股浓烈的血腥气息扑面而来。众人借着微弱的月光,只见眼前是一个满是鲜血的房间,地上横七竖八地躺着一些尸体,还有一条血淋淋的大腿,场景极其恐怖。
都奕看着这一切,淡淡地说了一句:“这些尸体似乎不像是今天刚死的。”他的这句话让项清心中的怀疑更加强烈了,他觉得都奕一定知道些什么。
大家都被这恐怖的场景吓得不轻,有人甚至忍不住呕吐起来。而就在这时,不远处又传来一阵轻微的响 ...
记一次动态注册路由导致的路由跳转阻塞问题
背景
最近在写的项目遇到这样一个问题:
页面在登录后,查询一个接口获取租户 ID,然后异步刷新页面,把获取到的租户 ID 挂载在路由路径里
在获取到租户 ID 后的这次刷新页面的路由守卫(Router Guard)的钩子里,代码会动态下载一段脚本并执行,该脚本会调用 Vue Router 的 addRoute() 方法动态注册路由
之后执行路由守卫的 next() 放行本次跳转
问题
问题来了,由于该次刷新页面是异步操作,而且动态下载脚本也是异步操作,有一定的几率,addRoute() 和 next()在同一个 Vue 的刷新任务队列里执行,然后就会发生路由跳转停止,反映到页面上,就是
页面点击登录后不再跳转到主页面
解析
之前有同事跟我说,这是因为 addRoute() 会打断路由跳转,所以我们写了一些代码来规避这件事
总的思路是,在这次异步 next() 之前发送事件通知脚本延后执行 addRoute(),这样做有一个问题,即延后多久执行 addRoute(),我们原先设定的是200ms,但结果是仍然有概率与 next() 运行在同一个任务队列里,再延长这个时间其实也不是最好的办法 ...
从 Vue2 到 Vue3(二):语法
从 Vue2 到 Vue3(二):语法
其实讲了那么多原理,目前还是不知道怎么写 Vue3,由是简单分享一下如何写的问题
起步
这是 Vue2 的写法
1234import Vue from 'vue'import App from './App.vue'new Vue({el: '#app', render: (h) => h(App)})
Vue3 的组合式 API 使用函数而不是声明选项的方式书写 Vue 组件,这也反应在了创建 Vue 实例上,工具方法需要引入,而不是直接挂载在 Vue 类上,这样做也有利于打包时的 TreeShaking 精确判断不必要的代码片段并将之移除
12345import { createApp } from 'vue'import App from './App.vue'const app = createApp(App)app.mount('#app')
选项式到组合式
组合式 API ...