From e65ddae133166e941e6c8d583443b426c2e376ec Mon Sep 17 00:00:00 2001 From: yk Date: Sun, 5 May 2024 11:49:13 +0800 Subject: [PATCH] something --- .../base-js/curry\345\222\214compose.md" | 86 +++---- .../promise\345\271\266\345\217\221.md" | 87 +++---- ...20\345\211\215\347\273\223\346\235\237.md" | 114 +++++---- public/categories/index.html | 4 +- public/categories/index.xml | 16 +- public/categories/vue/index.html | 10 +- public/categories/vue/index.xml | 15 +- "public/curry\345\222\214compose/index.html" | 100 ++++---- "public/curry\345\222\214compose/index.md" | 86 +++---- public/index.json | 2 +- public/index.xml | 17 +- public/js/giscus.min.js | 1 + .../index.html" | 6 +- public/posts/index.html | 6 +- public/posts/index.xml | 17 +- public/posts/page/2/index.html | 12 +- public/posts/page/3/index.html | 12 +- public/posts/page/4/index.html | 12 +- .../index.html" | 97 ++++---- .../promise\345\271\266\345\217\221/index.md" | 87 +++---- .../index.html" | 120 ++++----- .../index.md" | 114 +++++---- .../index.html | 6 +- public/sitemap.xml | 12 +- public/tags/javascript/index.xml | 7 +- public/tags/promise/index.xml | 8 +- .../index.html" | 4 +- .../index.html" | 182 +++++++------- .../index.md" | 168 +++++++------ .../index.html" | 227 ++++++++++++++++-- .../index.md" | 81 ++++++- .../index.html" | 4 +- .../index.html" | 4 +- .../index.html" | 146 +++++------ .../index.md" | 164 ++++++------- .../index.html" | 10 +- .../index.md" | 6 +- .../index.html" | 6 +- 38 files changed, 1175 insertions(+), 881 deletions(-) create mode 100644 public/js/giscus.min.js diff --git "a/content/posts/base-js/curry\345\222\214compose.md" "b/content/posts/base-js/curry\345\222\214compose.md" index 61103dc..cd906cc 100644 --- "a/content/posts/base-js/curry\345\222\214compose.md" +++ "b/content/posts/base-js/curry\345\222\214compose.md" @@ -14,8 +14,8 @@ tags: [JavaScript] 1. 声明式编程 比如 map 只关注输入和结果,用表达式来描述程序逻辑, 而 常规的 for 循环命令式控制过程还关注具体控制和状态变化 2. 纯函数 - 1. 仅取决于提供的输入 - 2. 不会造成或超出其作用域的变化。 比如修改全局对象或引用传递的参数,打印日志,时间等 + 1. 仅取决于提供的输入 + 2. 不会造成或超出其作用域的变化。 比如修改全局对象或引用传递的参数,打印日志,时间等 3. 引用透明 一个函数对于相同的输入始终产生相同的结果,那就是引用透明的 4. 不可变性 @@ -25,47 +25,50 @@ tags: [JavaScript] ### curry -柯里化,其实就是针对函数多个参数的处理,把多个参数变为可以分步接收计算的方式。形如`f(a,b,c) -> f(a)(b)(c)` +柯里化,其实就是针对函数多个参数的处理,把多个参数变为可以分步接收计算的方式。 + +`f(a,b,c) -> f(a)(b)(c)` 实现也比较简单: -```javascript +```js {lineNos=false} function curry(fn) { - return function curried(...args) { - if (args.length >= fn.length) { - return fn.apply(this, args); - } else { - return function (...args2) { - return curried.apply(this, args.concat(args2)); // 借助curried累加参数 - }; + const argLen = fn.length + return function curried(...args) { + if (args.length === argLen) { + return fn.call(this, ...args) + } else { + return function (...args2) { + return curried.call(this, ...[...args, ...args2]) // 累加参数 + } + } } - }; } // test -const sum = (a, b, c) => a + b + c; -const currySum = curry(sum); -console.log(currySum(1, 2, 3)); // 6 -console.log(currySum(1)(2, 3)); // 6 -console.log(currySum(1, 2)(3)); // 6 +const sum = (a, b, c) => a + b + c +const currySum = curry(sum) +console.log(currySum(1, 2, 3)) // 6 +console.log(currySum(1)(2, 3)) // 6 +console.log(currySum(1, 2)(3)) // 6 ``` 柯里化的孪生兄弟 -- 偏函数,个人见解: 就是在 curry 之上,初始化时固定了部分的参数,注意两者累加参数的方式不太一样哦。 -```js +```js {lineNos=false} /** * args 为固定的参数 */ function partial(fn, ...args) { - return function (...args2) { - const _args = args.concat(args2); - if (_args.length >= fn.length) { - return fn.apply(this, _args); - } else { - return partial.call(this, fn, ..._args); // 借助 partial 累加参数 + return function (...args2) { + const _args = args.concat(args2) + if (_args.length >= fn.length) { + return fn.apply(this, _args) + } else { + return partial.call(this, fn, ..._args) // 借助 partial 累加参数 + } } - }; } // test @@ -78,18 +81,19 @@ console.log(partialSum(1)(2)) // 103 compose 合成函数是把多层函数嵌套调用扁平化,内部函数执行的结果作为外部面函数的参数。 -```js -function compose() { - // 可以加个判断参数是否合格, 此处省略 - const fns = [...arguments] - return function () { - let lastIndex = fns.length - 1 - let res = fns[lastIndex].call(this, ...arguments) - while (lastIndex--) { - res = fns[lastIndex].call(this, res) +`a(b(c(d()))) -> compose(a,b,c,d)` + +```js {lineNos=false} +function compose(...fns) { + return function (...args) { + let fnsLen = fns.length + let lastIndex = fnsLen - 1 + let res = fns[lastIndex].call(this, ...args) + while (lastIndex--) { + res = fns[lastIndex].call(this, res) + } + return res } - return res - } } // test @@ -104,14 +108,14 @@ console.log(test(10, 20)) // 40 与之对应的是 pipe 函数,只不过是从左往右执行。这里就用 reduce 来实现一下吧: -```js +```js {lineNos=false} function pipe(...fns) { - return function (args) { - return fns.reduce((t, cb) => cb(t), args); - }; + return function (args) { + return fns.reduce((t, cb) => cb(t), args) + } } ``` ## 参考 -- [函数式编程入门教程](http://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html) +- [函数式编程入门教程](http://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html) diff --git "a/content/posts/base-js/promise\345\271\266\345\217\221.md" "b/content/posts/base-js/promise\345\271\266\345\217\221.md" index 77432c9..2854dda 100644 --- "a/content/posts/base-js/promise\345\271\266\345\217\221.md" +++ "b/content/posts/base-js/promise\345\271\266\345\217\221.md" @@ -4,44 +4,48 @@ date: 2022-09-20T14:41:20+08:00 tags: [JavaScript, promise] --- -一个比较经典的问题,就是 n 个 请求,实现一个方法,让每次并发请求个数是 x 个这样子。 +一个比较经典的问题,就是 n 个 请求,实现一个方法,让每次并发请求个数是 x 个。 其实在前端中应该是比较常用的应用,如果 n 个请求瞬间被发送到后端,这个是不合理的,应该控制在一定的范围内,当某个请求返回时,再去发起下个请求。 ## promise 关键点,一个限定数量的请求池,一个 promise 有结果后,再去加入下一个请求,递归直到所有结束。 -```js -const mockReq = function (time) { - return new Promise((resolve, reject) => { - setTimeout(() => { - resolve(time); - }, time); - }); -}; -const reqList = [1000, 2000, 2000, 3000, 3000, 5000]; -const res = []; +```js {open=true, lineNos=false, wrap=true, header=true, title=""} +const mockReq = time => { + return function () { + return new Promise(resolve => { + setTimeout(() => { + resolve(time) + }, time) + }) + } +} + +const reqList = [1000, 3000, 2000, 2000, 3000, 4000, 2000] +const reqs = reqList.map(item => mockReq(item)) /** * 核心就是利用递归调用请求,在then回调中自动加入请求池 */ -function concurrentPromise(limit) { - const pool = []; - for (let i = 0; i < limit; ++i) { - // pool.push(mockReq(reqList.shift()); - managePool(pool, mockReq(reqList.shift())); - } +const res = [] +function concurrent(reqs, limit) { + const pool = [] + for (let i = 0; i < limit; ++i) { + // pool.push(reqs[i]()) + poolControl(pool, reqs.shift(), reqs) + } } -function managePool(pool, promise) { - pool.push(promise); - promise.then((r) => { - res.push(r); - pool.splice(pool.indexOf(promise), 1); - if (reqList.length) managePool(pool, mockReq(reqList.shift())); - pool.length === 0 && console.log('ret', res); - }); +function poolControl(pool, req, reqs) { + pool.push(req) + req().then(r => { + res.push(r) + pool.splice(pool.indexOf(req), 1) + if (reqs.length) poolControl(pool, reqs.shift(), reqs) + if (pool.length === 0) console.log('🔥🔥🔥 ---', res) + }) } -concurrentPromise(3); +concurrent(reqs, 3) ``` 重点是: @@ -53,23 +57,22 @@ concurrentPromise(3); 通过 aync + promise.race 能更简单的控制。 -```js -async function concurrentPromise(limit) { - const pool = []; - for (let i = 0; i < reqList.length; ++i) { - const req = mockReq(reqList[i]); - pool.push(req); - req.then((r) => { - res.push(r); - pool.splice(pool.indexOf(req), 1); - if (pool.length === 0) console.log(res); - }); - if (pool.length === limit) { - await Promise.race(pool); +```js {open=true, lineNos=false, wrap=true, header=true, title=""} +async function concurrent(reqs, limit) { + const pool = [] + for (let i = 0; i < reqs.length; ++i) { + pool.push(reqs[i]()) + reqs[i]().then(r => { + res.push(r) + pool.splice(pool.indexOf(reqs[i]), 1) + if (pool.length === 0) console.log('🔥🔥🔥 ---', res) + }) + if (pool.length === limit) { + await Promise.race(pool) + } } - } } -concurrentPromise(3); +concurrent(reqs, 3) ``` 关键点:与原生 promise 维护一个请求池不同的是,直接通过**普通 for** 循环添加 await 和 Promise.race 来实现等待效果。 @@ -80,4 +83,4 @@ concurrentPromise(3); ## 参考 -- [async-pool](https://github.com/rxaviers/async-pool/blob/master/lib/es9.js) +- [async-pool](https://github.com/rxaviers/async-pool/blob/master/lib/es9.js) diff --git "a/content/posts/base-js/promise\346\217\220\345\211\215\347\273\223\346\235\237.md" "b/content/posts/base-js/promise\346\217\220\345\211\215\347\273\223\346\235\237.md" index 1754cdf..590635c 100644 --- "a/content/posts/base-js/promise\346\217\220\345\211\215\347\273\223\346\235\237.md" +++ "b/content/posts/base-js/promise\346\217\220\345\211\215\347\273\223\346\235\237.md" @@ -8,52 +8,60 @@ tags: [JavaScript, promise] axios 已经有了取消请求的功能: -```js -const CancelToken = axios.CancelToken; -let cancel; +```js {open=false, lineNos=false, wrap=true, header=true, title="已废弃"} +const CancelToken = axios.CancelToken +let cancel axios.get('/demo', { - cancelToken: new CancelToken((c) => { - cancel = c; - }) -}); + cancelToken: new CancelToken(c => { + cancel = c + }) +}) -cancel(); // 取消这个请求 +cancel() // 取消这个请求 /* ---------- 或者 ---------- */ -const CancelToken = axios.CancelToken; -const source = CancelToken.source(); - -axios.get('/user/12345', { - cancelToken: source.token -}).catch(function (thrown) { - if (axios.isCancel(thrown)) { - console.log('Request canceled', thrown.message); - } else { - // 处理错误 - } -}); - -axios.post('/user/12345', { - name: 'new name' -}, { - cancelToken: source.token -}) +const CancelToken = axios.CancelToken +const source = CancelToken.source() + +axios + .get('/user/12345', { + cancelToken: source.token + }) + .catch(function (thrown) { + if (axios.isCancel(thrown)) { + console.log('Request canceled', thrown.message) + } else { + // 处理错误 + } + }) + +axios.post( + '/user/12345', + { + name: 'new name' + }, + { + cancelToken: source.token + } +) // 取消请求(message 参数是可选的) -source.cancel('Operation canceled by the user.'); +source.cancel('Operation canceled by the user.') ``` -上方的 CancelToken 从 v0.22.0 版本被废弃,最新的 axios 使用的是 fetch 的 api `AbortController`: +上方的 CancelToken 从 v0.22.0 版本被废弃,最新的 axios 使用的是与 fetch 一样的 api `AbortController`: -```js -const controller = new AbortController(); +```js {open=true, lineNos=false, wrap=true, header=true, title=""} +const controller = new AbortController() -axios.get('/foo/bar', { - signal: controller.signal -}).then(function(response) { - //... -}); +axios + .get('/foo/bar', { + signal: controller.signal + }) + .then(function (response) { + //... + }) // 取消请求 controller.abort() ``` @@ -62,24 +70,24 @@ controller.abort() 首先我在"中断"上打了引号,因为 promise 一旦创建是无法取消的,所谓的”中断“,只是在合适的时候,提前结束 pending 状态而已,所以本文题目才是提前结束而不是“中断”。 -```js +```js {open=true, lineNos=false, wrap=true, header=true, title=""} const mockReq = function (time) { - const req = new Promise((resolve, reject) => { - setTimeout(() => { - resolve(time); - }, time); - }); - let abort = null; - const stopHandler = new Promise((resolve, reject) => { - abort = reject; - }); - const p = Promise.race([req, stopHandler]); - p.abort = abort; - return p; -}; - -mockReq(2000).then((res) => console.log(res)); -mockReq().abort(); + const req = new Promise((resolve, reject) => { + setTimeout(() => { + resolve(time) + }, time) + }) + let abort = null + const stopHandler = new Promise((resolve, reject) => { + abort = reject + }) + const p = Promise.race([req, stopHandler]) + p.abort = abort + return p +} + +mockReq(2000).then(res => console.log(res)) +mockReq().abort() ``` 其实核心就是借助另一个永远不会成功或失败的 promise 的 execute 函数,来让人可以手动改变 handle 的状态,进而影响 `Promise.race` 的执行。值得注意的是,req 仍然会执行完成,但是已经无意义了。 @@ -88,4 +96,4 @@ promise 超时控制原理一样,把一个设定超时时间的 promise 和正 ## 参考 -- [axios 文档-取消请求](https://www.axios-http.cn/docs/cancellation) +- [axios 文档-取消请求](https://www.axios-http.cn/docs/cancellation) diff --git a/public/categories/index.html b/public/categories/index.html index 4181d75..a86b662 100644 --- a/public/categories/index.html +++ b/public/categories/index.html @@ -217,9 +217,9 @@

xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> Vue 2

- Vue 源码中的设计美学 + Vue2 源码中的设计美学
- Vue2响应式原理 + Vue2 响应式原理
diff --git a/public/categories/index.xml b/public/categories/index.xml index 9306586..7d414ad 100644 --- a/public/categories/index.xml +++ b/public/categories/index.xml @@ -4,14 +4,7 @@ http://localhost:1313/categories/ Categories - 分类 - Hello World Hugo -- gohugo.iozh-CNericyuanovo@gmail.com (EricYuan) - ericyuanovo@gmail.com (EricYuan)Tue, 30 Apr 2024 00:00:00 +0000 - Vue - http://localhost:1313/categories/vue/ - Tue, 30 Apr 2024 00:00:00 +0000 - EricYuan - http://localhost:1313/categories/vue/ - - + ericyuanovo@gmail.com (EricYuan)Wed, 21 Feb 2024 00:00:00 +0000 Algorithm http://localhost:1313/categories/algorithm/ Wed, 21 Feb 2024 00:00:00 +0000 @@ -53,5 +46,12 @@ EricYuan http://localhost:1313/categories/tool/ + + Vue + http://localhost:1313/categories/vue/ + Sat, 30 Apr 2022 00:00:00 +0000 + EricYuan + http://localhost:1313/categories/vue/ + diff --git a/public/categories/vue/index.html b/public/categories/vue/index.html index 1c3548b..95dcfbb 100644 --- a/public/categories/vue/index.html +++ b/public/categories/vue/index.html @@ -158,12 +158,12 @@

 Vue

2024