当场没写出来,面试官劝我别紧张,说这道题很基础,可是面试后自己在这也没写出来...
.png)
当场没写出来,面试官劝我别紧张,说这道题很基础,可是面试后自己在这也没写出来...
.png)
综合了一下大家的回答,感觉👇这个代码能不费力看懂~
.png)
|
YumweyJun 20, 2022
1
看看 koa 的源码吧,这是很基础的 compose 了,实现方式很多,递归,迭代都可以
|
|
BiwoodJun 20, 2022 via Android
2
感觉还好,思路:遍历,使用.bind()把后一个 fn 作为参数绑定到前一个 fn 上,即前一个 fn 参数中的 next ,遍历完后执行第一个 fn 即可。
猜测一下,expressjs 这类框架的中间件大概是类似原理吧。 |
|
YumweyJun 20, 2022
3
|
|
YumweyJun 20, 2022
4
也可以看看 redux 的实现,应该都挺常见的
|
|
CbdyJun 20, 2022
5
一行代码的事情
export function compose(middlewares = (ctx, next) => (void 0)) { if (!middlewares || !middlewares.length) { return ctx => (void 0) } return ctx => middlewares[0](ctx, () => compose(middlewares.slice(1))(ctx)) } |
|
6
@Cbdy 是怎么做到一下子写出来的...看来这道题真的很基础,面试官没说错。
|
|
7
```
const compose = arr => { const run = lastArr => { if (lastArr.length === 0) { return; } const first = lastArr.shift(); first(() => run(arr)); }; return () => { run(arr); }; }; ``` 这样?运行结果是 ok 的,没做检查。 |
|
rabbbitJun 20, 2022
8
哎,想了十几分钟才有思路。现场肯定是写不出来了
function compose(arr) { const next = (fn = (() => {}), arr) => { fn(next.bind(this, arr[0], arr.slice(1))); }; return next.bind(this, arr[0], arr.slice(1)); } |
|
9
@cyrbuzz 对的,我刚刚自己又尝试了一下,写出来的与你思路一致... 看样子我是能做出来的...唉
|
|
10
|
|
TWorldIsNButThisJun 20, 2022 via iPhone
11
swr 的 middleware 就是这个结构
其他前端框架应该有不少类似的 |
|
desJun 20, 2022 via iPhone
12
忘了在哪里看到的了
arr.reverse().reduce((a, b) => () => b(a), Function.prototype)() |
|
rabbbitJun 20, 2022
13
哪里有类似 Leetcode 能刷这种题的题库吗?
|
|
CbdyJun 20, 2022
14
如果觉得 JS 版本太难懂,可以看一下 Java 版本
https://github.com/cbdyzj/nanometer/blob/main/common/src/main/java/nano/support/Onion.java |
|
KMpAn8Obw1QhPoEPJun 20, 2022
15
```JS
const compose = ([f, ...arr]) => arr.length ? () => f(compose(arr)) : () => f?.(() => { }); ``` |
|
16
没想到还有更简单的
```JS const compose = arr => arr.reduceRight((acc, cur) => () => cur(acc), () => { }); ``` |
|
unsizedJun 20, 2022
17
想了十几分钟,代码倒是简单,思路很重要。估计我面试时也会紧张写不出来。
// 递归 function compose(middlewares) { if (middlewares.length === 0) { return () => {} } const middleware = middlewares.shift() return middleware.bind(null, compose(middlewares)) } // 迭代 function compose(middlewares) { let res; for (let i = middlewares.length - 1; i >= 0; i--) { if (!res) { res = middlewares[i].bind(null, () => {}) } else { res = middlewares[i].bind(null, res) } } return res; } |
|
18
|
|
19
综合上面回答的缩减版()
const compose = ([fn, ...fns]) => () => fn?.(compose(fns)) |
|
isbaseJun 20, 2022
20
|
|
KMpAn8Obw1QhPoEPJun 20, 2022 via Android
21
@sweetcola 很极致 我喜欢
|
|
skies457Jun 20, 2022
22
const compose = ((self, [fn, ...fns]) => () => fn?.(self(self, fns)))((self, [fn, ...fns]) => () => fn?.(self(self, fns)), arr)
还可以升级一下难度,只使用匿名函数(逃 |
|
skies457Jun 20, 2022
23
const compose = arr => ((self, [fn, ...fns]) => () => fn?.(self(self, fns)))((self, [fn, ...fns]) => () => fn?.(self(self, fns)), arr)
少了 arr => ( |
|
molvqingtaiJun 20, 2022 via Android
25
洋葱圈模型还挺实用的,koa 就不用说了,比如前端使用的 redux 、vue-router 内部实现都是使用洋葱模型
我也这种模式封装了一个 http 客户端: https://github.com/molvqingtai/resreq |
|
chezs66Jun 20, 2022
26
这就是栈呀。。。无非是自己写一个栈,或用 js 自带的栈
|
|
zyxyz123Jun 20, 2022
27
const compose = (arr) => {
if (arr.length === 0) { return () => {} } return () => { arr[0](compose(arr.slice(1))) } } |
|
otakustayJun 20, 2022
28
const compose = handlers => handlers.reduceRight((out, v) => () => v(out), () => {});
手写倒有点难,电脑敲再简单调试一下下可以 |
|
AgassizJun 21, 2022 via iPhone
29
洋葱模型
|
|
walpurgisJun 21, 2022
30
middlewares = [fn1,fn2,fn3]
compose 展开后是这样 fn = () => fn1(() => fn2(() => fn3(() => {}))); 暴力拼接法 function compose(arr) { const fn = arr.pop(); let composed = () => fn(() => {}); while (arr.length > 0) { const fn = arr.pop(); composed = ((next) => () => fn(next))(composed) }; return composed; } |
|
wanacryJun 21, 2022 via iPhone
31
这是啥玩意 我也会 js 但是为啥我都看不懂
|
|
banmuyutianJun 21, 2022
33
才疏学浅,请教下这个洋葱模型是不是类似于 Spring Boot 的堆栈?
|
|
danhuaJun 21, 2022
34
为啥我第一眼感觉可以用异步来解决,不过异步比上面大佬们给出的方法要麻烦多了。
|
|
dtdths1Jun 21, 2022
35
洋葱圈模型
|
|
ryougifujinoJun 21, 2022
36
function compose(arr) {
let next = function () { } arr.reverse().forEach(fn => { const nextFn = next next = function () { fn(nextFn) } }) return next } |
|
ryougifujinoJun 21, 2022
37
@ryougifujino #36 个人感觉我这个思路很简单,确实就是洋葱圈模型。next 顾名思义,就是下一次要执行的函数,所以核心思路就是把下一次的函数放到 next 中去就行了。
|
|
38
@ryougifujino 说真的,我看不懂😂
|
|
LenicJun 25, 2022
39
建议看下 Array.prototype.reduce 方法
|
|
usdcAug 3, 2022
40
|
|
houchangxiaowangApr 22, 2023
41
图片挂了,重新帖下?
|